(dfs变枚举)洛谷P1467 循环数 Runaround Numbers

一、算法分析

本题显然可以用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;
	
}
发布了50 篇原创文章 · 获赞 7 · 访问量 1129

猜你喜欢

转载自blog.csdn.net/numb_ac/article/details/103646287
今日推荐