Numeric Keypad:多思考,别蛮力!

题目描述

The numberic keypad on your mobile phone looks like below:
123
456
789
 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)moveyour 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<=10^500,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

思路:

1.技巧一:想要取得一个大整数的各个位,不要一根筋想着%10,/10,这样的操作很麻烦。可以,考虑,to_string()函数,把一个数变成字符串可以很快的提取它的各个位。

2.我起初很傻的这样,如果一个大数N不合法,则从比N小的地方开始往下找,真是蠢至极。。。。你想想,如果一个数字是9111111111111,你后面再怎么找,都是不合法的,因为第一个数是9。

3.思路如下:在代码注释中可见。

1.在找小于它的最大值的时候,肯定是往‘9’上面靠拢,这点意识要有!

2.每改变一个数字,就把后面的所有位都置为9,显然是最大的。

3.每修改完一个数字,记得再次往前回溯比较。

当前数字>1,记得回溯比较,显然还是合法的。

当前数字=0,前面数字要借位,前面数字-1;但是,前面数字修改之后一定不能违反合法性。

#include <iostream>
#include <string>
using namespace std;


void locate(int digit,int&x,int&y)
{
    digit=digit?--digit:10;
    x=digit/3;
    y=digit%3;
}


bool canReach(int x,int y){
      int x0,y0,x1,y1;
      locate(x,x0,y0);
      locate(y,x1,y1);
      return x0<=x1&&y0<=y1;
}



int main()
{
   
    int n;
    
    for (cin>>n; n--; )
    {
        string curstr;
        cin>>curstr;
        int i=1;
        int len=curstr.size();
        while(i<len){
            int curNum=curstr[i]-'0';
            int preNum=curstr[i-1]-'0';
            if(!canReach(preNum,curNum)){
                if(curNum>=1){
                    curstr[i]--;//修改完当前数字后,要考虑到有没有影响到前一位到当前位的合法性。
                    			//显然此处还是合法的,所以不用i--;
                    for (int j = i+1; j < len; ++j) curstr[j]='9';
                }
                else{
                    curstr[i-1]--;
                    for (int j = i; j < len; ++j) curstr[j]='9';
                    i--;//这一步相当重要,比如测试996,你试试看如果没有这一步会怎么样。
                    //当996-->990-->989时,前一位被修改了,由9变为8,所以还是可能引起非法。所以要往前回溯一个。
                }
            }else
                ++i;
        }

        cout<<curstr<<endl;

    }



    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值