一、算法分析
本题显然可以用dfs来做,但是相对来讲,用枚举更加方便,我们从m+1开始进行枚举,找到的第一个满足条件的数就是答案,因而它的主程序是长这样的:
int main(){
cin>>m;
while(true){
m++; //要比m大的
if(work(m)){
cout<<m;
break;
}
}
return 0;
}
接下来,对于每次枚举,因为要按位处理,所以将其转化成数组,这里用到了vector的一个reverse转置功能。然后按照题意模拟即可。
二、代码及注释
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int m;
vector<int> a; //要考虑处理每一位,就将之转换成数组
int len; //保存a数组的长度
int pd[10];
bool trans(int x){ //很多函数的返回值都写成bool形式,有利于判断
a.clear();
while(x){
if(x%10==0) return false; //不能有0
a.push_back(x%10);
x/=10;
}
reverse(a.begin(),a.end()); //转置一下
len=a.size();
return true;
}
bool work(int x){
int pos=0; //起始走的位置
memset(pd,0,sizeof(pd));
if(!trans(x)) return false; //转换不成功(存在0)
for(int i=0;i<len;i++){ //主要就是要对数组进行处理,如果要每个走一遍,那就至少要走len遍
if(pd[a[pos]]) return false; //剪枝
pd[a[pos]]=1; //标记走过了
pos=(pos+a[pos])%len; //当前位置再加上要走的步数,再对len取余数
//if(pos==0) pos=len-1; //开始时候加了这一句,结果就一直死循环,后来就想通了,如果以0为起始下标则不能加这个
}
if(pos!=0) return false;
else return true; //上面的步数走完之后,如果没有跳出,自然就回到原点,这里加个if稳妥一些
}
int main(){
cin>>m;
while(true){
m++; //要比m大的
if(work(m)){
cout<<m;
break;
}
}
return 0;
}