POJ1780 Code 欧拉回路+非递归DFS

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

用DFS找一个欧拉回路,按照字典序输出路径。

由于状态过多,不能用递归,要用非递归实现DFS(好麻烦,,,),然后不能用stack会超时,自己写个数组吧,别偷懒了。

关于这题为什么会是欧拉回路呢。

首先题意:题目告诉我们了密码的长度为n (那么一个密码一共可能有10^n种可能),然后由于当输入密码长度大于n时,只有最后n为有效。这样我们只要用一个(10^n+n-1)长的数字序列,就能破解这个密码。至于为什么是这个长度,那是因为一共有10^n个状态分别拿出第一个数字排列下去,然后最后一个密码会多出n-1位。直接放在后面。这样实际上这个序列就是一个欧拉回路,它实际包含了10^n个密码(每个状态都出现了一次);


关于边与节点的定义。 加入密码为3位

那么我们的节点为前2为数,然后边会在前两位数后加上一个数形成的完整密码,然后后继点为新密码的后两位。

最后一共会有10^n条边,我们要找一个通路走完每一条边,也就是说每个密码状态都要出现一次,

这个题目实际上就是欧拉回路的旋转鼓轮的应用。

                 



Code
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1694 Accepted: 638

Description

KEY Inc., the leading company in security hardware, has developed a new kind of safe. To unlock it, you don't need a key but you are required to enter the correct n-digit code on a keypad (as if this were something new!). There are several models available, from toy safes for children (with a 2-digit code) to the military version (with a 6-digit code). 

The safe will open as soon as the last digit of the correct code is entered. There is no "enter" key. When you enter more than n digits, only the last n digits are significant. For example (in the 4-digit version), if the correct code is 4567, and you plan to enter the digit sequence 1234567890, the door will open as soon as you press the 7 key. 

The software to create this effect is rather simple. In the n-digit version the safe is always in one of 10n-1 internal states. The current state of the safe simply represents the last n-1 digits that have been entered. One of these states (in the example above, state 456) is marked as the unlocked state. If the safe is in the unlocked state and then the right key (in the example above, 7) is pressed, the door opens. Otherwise the safe shifts to the corresponding new state. For example, if the safe is in state 456 and then you press 8, the safe goes into state 568. 

A trivial strategy to open the safe is to enter all possible codes one after the other. In the worst case, however, this will require n * 10n keystrokes. By choosing a good digit sequence it is possible to open the safe in at most 10n + n - 1 keystrokes. All you have to do is to find a digit sequence that contains all n-digit sequences exactly once. KEY Inc. claims that for the military version (n=6) the fastest computers available today would need billions of years to find such a sequence - but apparently they don't know what some programmers are capable of...

Input

The input contains several test cases. Every test case is specified by an integer n. You may assume that 1<=n<=6. The last test case is followed by a zero.

Output

For each test case specified by n output a line containing a sequence of 10n + n - 1 digits that contains each n-digit sequence exactly once.

Sample Input

1
2
0

Sample Output

0123456789
00102030405060708091121314151617181922324252627282933435363738394454647484955657585966768697787988990
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<utility>
#include<vector>

using namespace std;

#define MAXN 1000000+100

struct node
{
    int v,id,next;
}edge[MAXN];

struct data
{
    int v,e;
}s[MAXN];

bool vis[MAXN];
int path[MAXN],top,st;
int head[MAXN],en;
int n;

void add(int u,int v,int id)
{
    edge[en].v=v;
    edge[en].id=id;
    edge[en].next=head[u];
    head[u]=en++;
}

void dfs(int u)
{
    data p;
    st=0;
    int t=head[u];
    p.v=u,p.e=t;
    s[st++]=p;
    vis[edge[t].id]=1;
    while(1)
    {
        if(t==-1)
        {
            data y=s[st-1];
            path[top++]=edge[y.e].id;
            st--;
            if(!st) break;

        }
        data x=s[st-1];
        t=head[x.v];
        while(t!=-1)
        {
            if(!vis[edge[t].id])
            {
                vis[edge[t].id]=1;
                p.v=edge[t].v,p.e=t;
                s[st++]=p;
                break;
            }
            t=edge[t].next;
        }
    }

}


int main()
{
    while(~scanf("%d",&n) && n)
    {
        if(n==1)
        {
            printf("0123456789\n");
            continue;
        }
        int cnt=1;//计算边数(状态)
        for(int i=1;i<=n;i++)
            cnt*=10;
        int len=cnt/10;//节点数
         memset(head,-1,sizeof(head)),en=0;
        for(int i=0;i<len;i++)
        {
            int tmp=i%(len/10);
            tmp*=10;
            for(int j=9;j>=0;j--)
            {
                add(i,tmp+j,i*10+j);
               // cout<<i*10+j<<endl;
            }
        }
        memset(vis,0,sizeof(vis));
        top=0;
        dfs(0);
        for(int i=top-1;i>0;i--)
            printf("%d",path[i]/(len));
        printf("%d\n",path[0]);
    }
    return 0;
}


欧拉图与汉密尔顿图的概念与应用 欧拉图与汉密尔顿图的概念与应用 以及他们的判定定理 立即下载

相关推荐

欧拉回路性质与应用探究欧拉回路性质与应用探究欧拉回路性质与应用探究

欧拉回路性质与应用探究欧拉回路性质与应用探究欧拉回路性质与应用探究

3.仇荣琦《欧拉回路性质与应用探究》1

【摘要】欧拉回路,又称“一笔画”,是图论中可行遍性问题的一种。本文首先介绍了欧拉回路的相关理论知识,以及求欧拉回路的算法。然后通过几个实例,介绍了与欧拉回路相关

C语言求无向图欧拉回路例子

自己用C写的无向图找欧拉回路的一个例子。主要用于数据结构的学习

欧拉图及其应用

提到欧拉图就要谈到哥尼斯堡七桥问题,最初有这样的一个问题的:18世纪中叶,东普鲁士哥尼斯堡城有一条贯穿全城的普雷格尔河,河中有两个岛,通过七座桥彼此相连,如下图所示问题是这样的:有人从四块陆地中的任意一块出发,按什么样的路线能做到每座桥只通过一次而最后返回原地。我们可以将整个问题抽象成下面的图进行解答:对于一个结点来说,每出一次节点,代表与结点相连的某一条边已经走过了即结点度数减1,与其相连的结点的度数也减1,如果上述哥尼斯堡有解的话,就应该存在这样一条回路从某个地点出发最后回到某个地点。

apprentice_eye的博客 2536

[转] 欧拉路径和欧拉回路及其应用

概念转自https://blog.csdn.net/qq_34454069/article/details/77779300 欧拉路径:在一个图中,从i点出发,能将每个边遍历一次最终达到j点的一条路径 欧拉回路:i=j时的欧拉路径 无向图 欧拉回路:在无向图中,只要每个点的度数均为偶数,那么必定存在欧拉回路。因为每个点的度是偶数,意味着总有成对的入边和出边,则不会出现卡在一个节点的情况。 ...

林鸿清的blog 1624

欧拉回路

时间复杂度分析 每一个顶点被访问一次每条边被访问两次O(|V|+|E|)O(|V|2) 对稠密图 |E|~|V|2O(|V|) 对稀疏图 |E|~|V|注意:爆栈问题欧拉路或欧拉回路问题, 就是有一条路径(或回路)由所有边构成,且每边只用一次。也称为一笔画问题,即连续的一次画出图的所有边,经过每条边一次且仅一次。...

老徐的博客 476

hdu 1116(欧拉图典型应用)

参考百度文库https://wenku.baidu.com/view/b245abaad1f34693daef3eae.html 欧拉回路 不重复地经过每条边的回路欧拉路径 不重复地经过每条边的路径。 欧拉图  存在欧拉回路的图。 半欧拉图 存在欧拉路径的图。 无向欧拉图的判定 ¡无向图存在欧拉回路的充要条件: 连通且没有奇点。 ¡ ¡无向图存在欧拉路径的充要条件: 连通且

sdnulixianrui的博客 1811

POJ 1780 Code (欧拉回路+非递归dfs)

题目地址:POJ 1780 还是求序列的欧拉回路。只不过这题有两坑。 第一坑是用数字来当点的话,会MLE,因为每个数字可以连10条边,100w条边会MLE,即使用vector也会TLE。这题可以用边来记录,对于n为1时直接输出,然后后面的,比如12,23这两个点就用边权值为123来表示这两个点,这样就把点和边的范围都缩小了10倍。 第二坑是用递归的dfs会爆栈

scf0920 1535

POJ1780 Code——欧拉回路非递归DFS

点这里 题意: 有个保险箱子是n位数字编码,当正确输入最后一位编码后就会打开(即输入任意多的数字只有最后n位数字有效)……要选择一个好的数字序列,最多只需按键10n + n - 1次就可以打开保险箱子,即要找到一个数字序列包含所有的n位数一次且仅一次。 题解: 为什么是按键10n + n - 1次。 不管你按键多少次,判断密码是否正确都是判断你按键的最后n位数,也就是说我们不需要真的按 n * 10n 个数字,只要一长串的数字当中出现过密码就行。 欧拉回路。 冥冥之中就有感觉是一道欧拉回路的问题,但为什

lllllan 286

poj 1780 Code (欧拉回路+非递归dfs)

Code Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1746   Accepted: 655 Description KEY Inc., the leading company in security hardware, has developed a new

To be what you what to be! 1410

POJ 1780 Code欧拉回路+非递归dfs

http://poj.org/problem?id=1780 题意:有个保险箱子是n位数字编码,当正确输入最后一位编码后就会打开(即输入任意多的数字只有最后n位数字有效)……要选择一个好的数字序列,最多只需按键10n+n-1次就可以打开保险箱子,即要找到一个数字序列包含所有的n位数一次且仅一次。序列要为字典序。 思路: 对于当前长度为n-1的序列,其后添加一个数字,使得添加后的序列没有...

weixin_30257433的博客 141

POJ 1780 Code(欧拉回路+模拟栈)

POJ 1780 Code(欧拉回路+模拟栈) http://poj.org/problem?id=1780 题意:(题意较复杂)大致思想是给你一个n,表示一个由0-9数字构成的n位密码.这个解锁过程如下:锁一直读入所有内容.只要当它最后读入的n个数字与密码吻合,那么就表示解锁了.现在要你输出一个长度为10^n+n-1的数字序列,这个数字序列包括了n位密码的所有可能.(也就是说输入这个序列,必

code 1806

欧拉回路和一笔画问题

信息学竞赛系列教程,欧拉回路欧拉路径的基本性质,一笔画问题的两种不同解法。

HDU2894 DeBruijin——欧拉回路非递归DFS+构造)

点这里 题意: 中文题面,相信你看到的,不再赘述。 题解: 今天做到的欧拉回路构造第三次了,可参考POJ1780 Code——欧拉回路非递归DFS)。 过程中犯的错: mod: 每次循环pre都要更新,而pre的更新运算又与mod相关,mod的大小应为2k-2。 pre: pre的更新一直弄错,pre = (pre % mod) * 2 + deg[pre] - 1;这个不解释可能过几天我自己也忘记了。意为剪去pre的第一位数字(即pre % mod)之后加上末尾新的数字,十位数肯定是处理不了的,

lllllan 256

POJ 1780 - Code 非递归..输出欧拉回路边路径..

题意:                          给一个进制k(1~5)..输出一种方案使得0~10^k-1排成一排(相邻的每k位都为不同的数,所以长度严格为10^k+k-1),,,并且字典序最小..                 题解:                         想了好久..写了好久..看了别人的代码..才完全明白...解释几个地方:

zzyzzy12 1651

HDU4850 Wow! Such String!——欧拉回路非递归DFS+构造+字符串)

点这里 题意: 给定一个n,要求输出一个长度为n的字符串,并且不会有长度大于等于4的重复的子串,不能得到输出impossible。 题解: 这题就跟POJ1780 Code——欧拉回路非递归DFS)很像。无非这里变成了字符串处理起来烦一点点 ,也就亿点点。 构造。 当然了,能重复的子串长度不能超过3,已经可以写一个很长很长的字符串了,当然是先构造好一个条件允许下最长的字符串,然后输出要求长度就行了。 点。 既然是欧拉回路的问题,点是什么,是构造到当前位置时,前三位字母构成的字符串。 边。 所有的点,后

lllllan 212

poj1780 Code 裸的欧拉回路

Code 忙了好久,终于搞定了,每次将不会的题琢磨完了,都感觉是一次小小的进步,庆祝一下下。。呵呵 首先是建图,题意要求所有的n位数编码成一个数字串,每个n位数只出现一次,可以把n位数看成边,那么可以把它的前n-1位看成点A,后n-1一位看成点B,那么它就是A->B的一条边了,这样我们就可以对10^(n - 1)个点建图,每个节点对另外10个点有边,找一次欧拉回路就行了。 这题有一难点...

weixin_30608131的博客 88

POJ1780 Code欧拉路径)

n位密码,要用尽可能短的序列将n位密码的10n种状态的子串都包括,那么要尽量地重合。 题目已经说最短的是10n+ n - 1,即每一个状态的后n-1位都和序列中后一个状态的前n-1位重合。 这题是经典的欧拉路径问题吧,用n位数字10n种状态来作为边,而用重合的n-1位数字表示点。 具体的建图,每个点都引出10条边(十进制),这10条边就代表着10个n位数,前n-1位的数就代表那个点,然后连...

weixin_30492601的博客 103

欧拉

   欧拉路和欧拉回路的概念   欧拉路: 从图中某个点出发遍历整个图,图中的每条边通过且只通过一次。   欧拉回路: 起点和终点相同的欧拉路。   度数: 一个点上连接的边的数量称为这个点的度数。在无向图中,如果度数是奇数则这个点称为奇点,否则则称为偶点。在有向图中有出度和入度。 欧拉路和欧拉回路是否存在 首先图应该是连通图。而图的连通性用DFS或并查集来判断 无向连通图的判断条件: 存在欧拉回路: 图中的点全都是偶点。 存在欧拉路: 图中只有两个奇点,其中一个奇点是起点,另一个是终点。 不可能

lllllan 468
上一篇: Ural1713 Key Substrings 后缀数组
下一篇: HDU2894 DeBruijin 欧拉回路
Albafica
博客等级 码龄15年 98粉丝 359原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值