hihocoder #1153 : Numeric Keypad

描述

The numberic keypad on your mobile phone looks like below:

1 2 3
4 5 6
7 8 9
0

Suppose you are holding your mobile phone with single hand. Your thumb points at digit 1. Each time you can 1) press the digit your thumb pointing at, 2) move your thumb right, 3) move your thumb down. Moving your thumb left or up is not allowed.

By using the numeric keypad under above constrains, you can produce some numbers like 177 or 480 while producing other numbers like 590 or 52 is impossible.

Given a number K, find out the maximum number less than or equal to K that can be produced.
输入

The first line contains an integer T, the number of testcases.

Each testcase occupies a single line with an integer K.

For 50% of the data, 1 <= K <= 999.

For 100% of the data, 1 <= K <= 10500, t <= 20.
输出

For each testcase output one line, the maximum number less than or equal to the corresponding K that can be produced.
样例输入

3
25
83
131

样例输出

25
80
129

  基本思想是一位位地后移,每次后移一位就比较和原串的大小,如果比原串大,在该位取可以取到的,小一点的数。如果该位所有数取完了都比原串大,就回到上一位,取可以取到的小一点的数,在进入下一位,重复上述步骤。首先列出每个数通过右移或者左移可以到达的数(包括自己,我第一遍就是这里出错了),从大到小保存在vector数组中:
  

NumAccessalbe[0] = vector<int>{ 0 };
NumAccessalbe[1] = vector<int>{ 8,7,6,5,4,3,2,1,0 };
NumAccessalbe[2] = vector<int>{ 9,8,6,5,3,2,0 };
NumAccessalbe[3] = vector<int>{ 9,6,3 };
NumAccessalbe[4] = vector<int>{ 9,8,7,6,5,4,0 };
NumAccessalbe[5] = vector<int>{ 9,8,6,5,0 };
NumAccessalbe[6] = vector<int>{ 9,6 };
NumAccessalbe[7] = vector<int>{ 9,8,7,0 };
NumAccessalbe[8] = vector<int>{ 9,8,0 };
NumAccessalbe[9] = vector<int>{ 9 };

  下面举个例子,例如131:

  1. 第一位取1,然后前进到第二位,此时结果为1
  2. 第二位取3,然后前进到第三位,此时结果为13
  3. 在第三位取9,6,3都会比131大,因此取值失败,返回到上一位,此时结果是1
  4. 回到第二位后,取比3小一点的数2,前进到第二位,此时结果是12
  5. 在第三位,可以取到9(131>129),此时结果是129
  6. 所有的位都处理完毕,输出最终结果129

      由上述过程可以看出,算法的过程中会出现回退的情况(第二位取3,前进,但是第三位没有数满足条件,回退到第二位)因此采用DFS,拥递归的方式搜索。下面是AC代码:
      

//Numeric Keypad
#include<iostream>
//#include<map>
#include<string>
#include<string.h>
#include<queue>
#include<stack>
#include<vector>
#include <cstdio>
#include<fstream>
#include<algorithm>
using namespace std;

#define Min(a,b) a<b?a:b
#define INF 1000000005
#define Num 100000+5
typedef struct {//每个节点的结构
    int X;
    int Y;
    int ID;
    int LinkNode[4];//分别对应X上的一前一后和Y上的一前一后,beforeX, afterX,beforeY, afterY 
} Location;

#define Max 10e500+5
vector<int> NumAccessalbe[10];//存放下一个能到达数的vector
string str;//原串
string jieguo;//结果串


int Loop(int deep, int num)
{
    int flag = 0;
    jieguo.push_back(num + '0');//将这个数放入结果中
    if (str.compare(jieguo) >= 0) {//jieguo较小
        if (deep == str.length() - 1) {//到了最后一位
                flag = 1;
        }
        else {//还在原串中间
            int i = 0;
            for (i = 0; i < NumAccessalbe[num].size(); i++)//从大到小的顺序进行尝试,使最后的结果最大
            {
                if (Loop(deep + 1, NumAccessalbe[num][i])) {//如果这个数可行
                    flag = 1;//标记可行
                    break;//一旦找到可行解,立即退出
                }
            }
            if (i >= NumAccessalbe[num].size())//如果尝试了所有的数都不行
                flag = 0;//标记不可行
        }
    }
    else //结果串较大
        flag = 0;//标记不可行
    if (flag) return 1;//如果标记是可行的,返回可行
    else {//标记是不可行的
        jieguo.pop_back();//删除最后一个数
        return 0;//返回不可行
    }
}

int LuShi()
{
    NumAccessalbe[0] = vector<int>{ 0 };
    NumAccessalbe[1] = vector<int>{ 8,7,6,5,4,3,2,1,0 };
    NumAccessalbe[2] = vector<int>{ 9,8,6,5,3,2,0 };
    NumAccessalbe[3] = vector<int>{ 9,6,3 };
    NumAccessalbe[4] = vector<int>{ 9,8,7,6,5,4,0 };
    NumAccessalbe[5] = vector<int>{ 9,8,6,5,0 };
    NumAccessalbe[6] = vector<int>{ 9,6 };
    NumAccessalbe[7] = vector<int>{ 9,8,7,0 };
    NumAccessalbe[8] = vector<int>{ 9,8,0 };
    NumAccessalbe[9] = vector<int>{ 9 };
    int N;
    cin >> N;
    while (N--)
    {
        str.clear();
        jieguo.clear();
        cin >> str;
        int i = 0;
        for (i = str[0] - '0'; i > -1; i--)//按照从大到小的顺序进行尝试
        {
            if (Loop(0, i)) {//如果这个尝试可行。就立即退出
                break;
            }
        }
        cout << jieguo << endl;//输出结果串
    }
    return 0;
}

int main()
{
    streambuf * oldbuf = cin.rdbuf((new ifstream("C:\\Users\\yzc\\Desktop\\input.txt"))->rdbuf());//重定向,OJ时将它注释掉
    //cout << LuShi() << endl;
    LuShi();
    system("pause");
    return 0;
}
点赞