USACO 2.2.3 Runaround Numbers dfs

题目大意就是给出一个M,求比M大得最小的一个“循环数”
  • 例如:81362
  • 如果你从最左边的数字开始 ( 在这个例子中是8) 数最左边这个数字个数字到右边(回到最左边如果数到了最右边),你会停止在另一个新的数字(如果没有停在一个不同的数字上,这个数就不是循环数). 就像: 8 1 3 6 2 从最左边接下去数8个数字: 1 3 6 2 8 1 3 6 所以下一个数字是6
  • 重复这样做 (这次从“6”开始数6个数字) 并且你会停止在一个新的数字上: 2 8 1 3 6 2, 也就是2.
  • 再这样做 (这次数两个): 8 1
  • 再一次 (这次一个): 3
  • 又一次: 6 2 8 这是你回到了起点, 在从每一个数字开始数1次之后. 如果你在从每一个数字开始数一次以后没有回到起点, 你的数字不是一个循环数。

此题给的约束条件太好了,刚好是全排列的要求,我用全排列来枚举数,然后看它是不是“循环数”,比赛的时候怎么没想到..

这是bfs还是dfs?用dfs写的bfs?..

View Code
#include <stdio.h>
#include <string.h>

int n,k,len,vis[10],mark[10];

void f(int x)
{
int i;
while (x)
{
k++;
x/=10;
}
}

int judge()
{
int i,t=0,used[10]={0};
for (i=1;i<=len;i++)
{
t=(mark[t]+t)%len;
if(used[t])return 0;
used[t]=1;
}
return 1;
}

int dfs(int i,int data)
{
int j;
if(i==len)
{
if(data>n)
{
if(judge())return 1;
}
return 0;
}
for (j=1;j<=9;j++)
{
if(!vis[j])
{
vis[j]=1;
mark[i]=j;
if(dfs(i+1,data*10+j))return 1;
vis[j]=0;
}
}
return 0;
}

int main()
{
int i;
while (scanf("%d",&n)!=EOF)
{
k=0;
f(n);
for (i=k;;i++)
{
len=i;
memset(vis,0,sizeof(vis));
if(dfs(0,0))break;
}
for (i=0;i<len;i++)
{
printf("%d",mark[i]);
}
printf("\n");
}
return 0;
}


posted @ 2011-10-22 19:45  104_gogo  阅读(189)  评论(0编辑  收藏  举报