先打表预处理(lr[i][j]表示j可以再i后面出现)
然后直接扫一遍(注意有的时候要回退数位)
另外还是要细心,之前wa了两次都是因为一个小细节的错误。。。
#include <iostream>
#include <cstring>
using namespace std;
bool lr[10][10];
int map[4][5];
int main()
{
// freopen("aa.txt","r",stdin);
int i,j,k,r,n;
bool flag=true;
char p[505];
for(i=0;i<=9;i++) //lr的打表
memset(lr,false,sizeof(lr));
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
map[i][j]=(i-1)*3+j;
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
for(k=1;k<=3;k++)
for(r=1;r<=3;r++)
if(i<=k&&j<=r)
lr[map[i][j]][map[k][r]]=true;
lr[1][0]=lr[2][0]=lr[4][0]=lr[5][0]=lr[7][0]=lr[8][0]=lr[0][0]=true;
cin>>n;
getchar(); //这个是跳过回车
while(n--) {
gets(p);
j=strlen(p);
for(i=0;i<j-1;i++) { //如果满足lr,直接考虑下一位
if(lr[p[i]-'0'][p[i+1]-'0'])
continue;
flag=false;
break;
}
if(!flag) { //不满足把i+1位的值减小试探,均不成功回退一位
while(i>=0) {
r=p[i+1]-'0'-1;
while(r>=0) {
if(lr[p[i]-'0'][r]) {
flag=true;
p[i+1]=r+'0';
i+=2;
break;
}
r--;
}
if(flag)
break;
i--;
}
if(!flag) {
i=1;
p[0]--;
}
if(p[i-1]=='0') //就是这儿了,之前把'0'写成0...
k=0;
else
k=9;
for(;i<j;i++)
p[i]=k+'0';
}
puts(p);
}
}