Code(poj 17801)

求出一个长度为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\n");
        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("\n");
}
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;
}
View Code

 

posted @ 2016-08-25 21:54  karles~  阅读(215)  评论(0编辑  收藏  举报