poj 1780 Code

//题目描述:
KEY公司开发出一种新的保险箱。要打开保险箱,不需要钥匙,但需要输入一个正确的、由
n位数字组成的编码。这种保险箱有几种类型,从给小孩子玩的玩具(2位数字编码)到军用型的
保险箱(6位数字编码)。
当正确地输入最后一位编码后,保险箱就立刻打开了。保险箱上没有“确定”键。当你输入
超过n位数字,则只有最后n位数字有效。例如,对一种4位数字编码的型号,如果正确的编码
为4567,你想输入的编码为1234567890,则保险箱的门会在你输入数字7后马上就打开了。
为了达到这种效果所需要设计的软件其实很简单。对n位数字编码的型号,保险箱始终处于
10
(n-1)
种内部状态之一。保险箱的当前状态只需用最后输入的n-1位数字表示,其中有一种状态(例
如,对前面的例子,就是456)被记为“开锁状态”。如果保险箱处于“开锁状态”,且输入最后
一位正确的数字(例如,在上面的例子中就是7),保险箱的门就打开了;否则保险箱切换到对应
的新状态。例如,如果保险箱的当前状态为456,接着输入8,则保险箱的状态切换到568。
为了开保险箱,一个繁琐的策略是一位接一位地输入所有可能的编码。然而,在最坏情况下,
这需要按键n×10
n次(有10
n组可能的编码,每个编码有n位)。而选择一个好的数字序列,最
多只需要按键10
n
+ n - 1次就可以打开保险箱了:你需要做的就是找到一个数字序列包含所有的
n位数一次且仅一次。KEY公司宣称,对军用型号(n = 6),当今最快的计算机也需要数十亿年
的时间才能找到这样的数字序列,但是很显然他们不知道有些程序员能在几分钟就能找到这样的
数字序列。


// 求序列的方法为:对于当前长度为n-1的序列, 其后添加一个数字, 使得添加后的序列没有
// 在前面出现过

// 我先用递归写了下 然后改成栈模拟 不然直接来还真是不好写
#include <iostream> #include <string> #include <map> #include <algorithm> #include <queue> #include <math.h> #include <stdio.h> #include <string.h> #include <vector> using namespace std; #define MOD 1000000007 #define maxn 1000100 int ls[maxn/10]; int ans[maxn],st[maxn]; int s,a; /*int cnt;用递归会爆的、、、 void dfs(int n,int m,int dp){ int v,u=n%m; dp++; while(ls[u]<10){ v=u*10+ls[u]; ls[u]++; dfs(v,m,dp); ans[cnt++]=v%10; u=v%m;if(ls[u]>=10) u=v/10; } printf("dp=%d\n",dp); }*/ // 对于当前长度为n-1的序列, 其后添加一个数字, 使得添加后的序列没有在前面出现过
void search(int v,int m){ int w; while(ls[v]<10){ w=v*10+ls[v];ls[v]++; st[s++]=w; v=w%m; } } int main(){ int n,m; int i; while(scanf("%d",&n),n){ for(m=1,i=1;i<n;i++) m=m*10; for(i=0;i<=m;i++) ls[i]=0; s=a=0; search(0,m); // cnt=0; // dfs(0,m,0); // printf("\n"); int v; while(s){ v=st[--s]; ans[a++]=v%10; v=v/10; search(v,m); } for(i=1;i<n;i++) printf("0"); for(i=a-1;i>=0;i--) printf("%d",ans[i]); printf("\n"); } return 0; }

 

你可能感兴趣的:(code)