• POJ1780 Code(欧拉路径)


    n位密码,要用尽可能短的序列将n位密码的10n种状态的子串都包括,那么要尽量地重合。

    题目已经说最短的是10n + n - 1,即每一个状态的后n-1位都和序列中后一个状态的前n-1位重合。

    这题是经典的欧拉路径问题吧,用n位数字10n种状态来作为边,而用重合的n-1位数字表示点。

    具体的建图,每个点都引出10条边(十进制),这10条边就代表着10个n位数,前n-1位的数就代表那个点,然后连向这个边代表数的后n-1位代表的点。。

    比如n等于3的时候这么建图(假设密码是二进制,十进制太多了):

    这样子如果图存在欧拉路径,那么就能构成最短的10n + n - 1序列包含所有n位10进制密码的子串,而这个序列就通过每条边表示数字的最后一位来构造。

    而这题听说不用真正地建图,DFS就行了。

    DFS要写成非递归的,POJ好像不能手动扩栈。

    改写非递归也不难:每个结点会被访问10次,每一次从0到9扩展结点入栈;访问第11次时出栈并还原,相当于递归的回溯部分了。

    另外这题要字典序最小。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 using namespace std;
     5 
     6 int n,pow[]={1,10,100,1000,10000,100000,1000000};
     7 int cnt[1000000],stack[1000010];
     8 bool vis[1000000];
     9 void dfs(){
    10     memset(vis,0,sizeof(vis));
    11     vis[0]=1;
    12     memset(cnt,0,sizeof(cnt));
    13     int top=0;
    14     stack[++top]=0;
    15     while(top!=pow[n]){
    16         int u=stack[top];
    17         if(cnt[u]==10){
    18             vis[u]=0; cnt[u]=0;
    19             --top;
    20             continue;
    21         }
    22         ++cnt[u];
    23         int v=(u*10+cnt[u]-1)%pow[n];
    24         if(vis[v]) continue;
    25         vis[v]=1;
    26         stack[++top]=v;
    27     }
    28     for(int i=1; i<=top; ++i) putchar(stack[i]%10+'0');
    29 }
    30 int main(){
    31     while(~scanf("%d",&n) && n){
    32         for(int i=1; i<n; ++i) putchar('0');
    33         dfs();
    34         putchar('
    ');
    35     }
    36     return 0;
    37 } 
  • 相关阅读:
    八、基本数据结构(图形结构)
    七、基本数据结构(树形结构)
    4、使用 ImportTsv 将 Hive 数据导入 Hbase
    六、跳表
    五、二分法查找
    四、归并排序 && 快速排序
    一、kafka 介绍 && kafka-client
    三、排序之冒泡、插入、选择
    二、YARN
    三、synchronized & lock
  • 原文地址:https://www.cnblogs.com/WABoss/p/5114345.html
Copyright © 2020-2023  润新知