求出一个长度为10^n+n-1的序列,其中包含了所有的n位数(一共10^n个数,从00000(n个0)~10^n-1)
/* 典型的欧拉回路题目 对于n=4为密码想要序列最短 那么 1234 234? 这两个一定挨着, 我们就把123和34?之间连一条边权为1234?的边,这样把所有的边只找一遍, 就把所有的点连了起来 */ #include<cstdio> #include<cstring> #include<iostream> #define M 1000010 using namespace std; int head[M],vis[M],stack[M],ans[M],n,k,cnt,m; struct node { int v,pre,t; };node e[M]; void add(int x,int y,int z) { ++cnt; e[cnt].v=y; e[cnt].t=z; e[cnt].pre=head[x]; head[x]=cnt; } void dfs() { int top=1;stack[1]=0; while(top) { int i=stack[top--];bool flag=false; for(int j=head[i];j;j=e[j].pre) if(!vis[e[j].t]) { vis[e[j].t]=1; stack[++top]=i; stack[++top]=e[j].v; flag=true;break; } if(!flag)ans[++m]=i; } } void init() { if(n==1) { printf("0123456789 "); return; } k=1; for(int i=1;i<n;i++)k*=10; for(int i=0;i<k;i++) { int x=i%(k/10); for(int j=9;j>=0;j--) { int y=x*10+j,z=i*10+j; add(i,y,z); } } m=0; dfs(); for(int i=1;i<n-1;i++)ans[++m]=0; printf("%d",ans[m]); for(int i=m-1;i>=1;i--)printf("%d",ans[i]%10); printf(" "); } int main() { while(scanf("%d",&n)==1) { if(!n)break; memset(e,0,sizeof(e)); memset(head,0,sizeof(head)); memset(vis,0,sizeof(vis)); memset(ans,0,sizeof(ans)); cnt=0; init(); } return 0; }