hiho 1182 : 欧拉路·三

1182 : 欧拉路·三

这时题目中给的提示:

小Ho:是这样的,每次转动一个区域不是相当于原来数字去掉最左边一位,并在最后加上1或者0么。

于是我考虑对于"XYYY",它转动之后可以变成"YYY0"或者"YYY1"。我就将所有的数字0~2^N-1看作2^N个点,连接所有的("XYYY","YYY0"),("XYYY","YYY1")。

比如当N=3时,我得到了这样一个图:

我要做的就是找一条路径,从一个点出发,走过所有的点后,再回到起点。但是我发现好像很难的样子。

小Hi:那当然了。你这样构造出来的路径叫做哈密顿回路,不是那么容易可以求解的。

小Ho:哎??那我应该怎么做。

小Hi:其实你的想法是没问题的,但是需要进行一下变换。在你的构图中我们是用点来表示数字,所以需要经过每一个点。如果我们用边来表示每一个数字呢?

小Ho:怎么用边表示数字?

小Hi:其实也很简单,比如说数字"10011",分别删掉它第一个数字和最后一个数字,得到"1001","0011"。然后我们连接一条从"1001"到"0011"的有向边,表示数字"10011"。则我们可以得到构图的方法:

对于N,我们构造一个包含2^(N-1)个点和2^N条边的图,点的编号从0到2^(N-1)-1。编号为i的点表示数字i。对于任意两个点,如果点i,点j满足点i的后n-2个数字和点j的前n-2个数字相同,则我们连接有向边(i,j)。而边(i,j)表示了数字((i << 1)+(j & 1))。比如对于N=3的时候,我们可以得到:

可以很容易证明对于任意不同边(i,j),其表示的数字一定不同。

小Ho:这样构图话,只要找到一条欧拉回路就可以了。但是一定会有欧拉回路么?

小Hi:当然能了,对于有向图,其存在欧拉路的条件是,至多有两个点的入度不等于出度,且这两个点满足:其中一个点入度比出度多1,另一个点出度比入度多1。

若所有点的入度都等于出度,则一定存在欧拉回路。这可以通过和无向图欧拉路同样的方法进行构造证明。

而我们构造的图,由构造方法可以知道对于任意一个点,其入度一定为2,出度一定为2。所以它必定存在欧拉回路。

在有向图中找欧拉路的方法,也仍然可以使用Fleury算法。写成伪代码的话:

DFS(u):
	While (以u为起点,且未被删除的边e(u,v))
		删除边e(u,v)
		DFS(v)
	End
	PathSize ← PathSize + 1
	Path[ PathSize ] ← u
		

但是,有一点要注意,在使用Fleury算法计算有向图的欧拉路时,我们需要将path[]倒序输出才能得到正确的路径。

小Ho:那找到欧拉回路之后呢?

小Hi:找到欧拉回路之后只要对该条欧拉回路进行拼接就可以得到我们目标的圆盘状态了。

小Ho:好,我大概明白了。我这就来试试!

题目分析:

提示中说的很清楚: 好好看看上面的讲解。 很聪明的地方是把图一变成了图二(图二也就是用边表示n位二进制可以表示的所有数。n=3时, 是0~7),节省了空间。  如果存在一个欧拉回路, 也就是存在一条路径每条边都走过并且只走一遍, 最后回到原点, 那么就可以说这个转盘可以表示n位二进制可以表示的所有数。用fleury求路径, 边球路径边记录,fleury不明白点这里

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;

int n, top, key, final[40000], ans[40000];
vector<int> vec[17000];

void init()//初始化把所有边标记出来
{
    for(int i = 0; i < (1 << n - 1); i++)
    {
        int j = i << 1; // 点i向左移一位
        int t = 1 << (n - 1);
        j = j & (t - 1);//舍去第一位
        vec[i].push_back(j); //最后一位加0
        vec[i].push_back(j+1); //最后一位添1
    }
}
void dfs(int x)
{
    ans[++top] = x;
    if(vec[x].size() > 0)
    {
        int tmp = vec[x][0];
        vec[x].erase(vec[x].begin()+0);//要记得删除便利过的点
        dfs(tmp);
    }
}
void fleury(int x)
{
    top = 1;
    ans[top] = x;
    while(top > 0)
    {
        if(vec[ans[top]].size() > 0)//如果可扩展, 则dfs可扩展的哪条路线
        {
            top--;
            dfs(ans[top+1]);
        }
        else//该点x没有其他的边可以先走了(即不可扩展), 那么就用final记录下来
        {
            final[++key] = ans[top];
            //ans只是记录路径的中间记录, 可能会变, 一定要用final做最后的记录
            top--;
        }
    }
}
int main()
{
    while(scanf("%d", &n) != EOF)
    {
        for(int i = 0; i < (1 << n); i++) vec[i].clear();
        init();
        key = 0;
        fleury(0);
        for(int i = 1; i <= (1 << n); i++)//将路径的每个值的最后一个二进制的值求出即可
        {
            int tmp = final[i] & 1;
            printf("%d", tmp);
        }
        cout << endl;
    }
    return 0;
}
时间: 2024-10-15 21:35:20

hiho 1182 : 欧拉路·三的相关文章

hiho 1182 : 欧拉路&amp;#183;三

1182 : 欧拉路·三 这时题目中给的提示: 小Ho:是这种.每次转动一个区域不是相当于原来数字去掉最左边一位,并在最后加上1或者0么. 于是我考虑对于"XYYY",它转动之后能够变成"YYY0"或者"YYY1".我就将全部的数字0~2^N-1看作2^N个点.连接全部的("XYYY","YYY0"),("XYYY","YYY1"). 比方当N=3时,我得到了这样一个

hihoCoder #1182 欧拉路&#183;三 (变形)

题意:写出一个环,环上有2^n个格子,每个格子中的数字是0或1,相连着的n个格子可以组成一个数的二进制,要求给出这2^n个数字的序列,使得组成的2^n个数字全是不同的.(即从0到2^n-1) 思路:构造一个图,但是只需要考虑边,每条边假设为n个0/1组成的串,即此图有2^n条边,每边代表1个数字.若两边经过同一个点,则可以从一条边k经过 (k<<1)+0/1就是左边去掉1位,再左移一位,再在后面添加0或1,就相当于切换到另外一边.既然可以在后面添加0或1,那么就相当于一个点有两条出边,那么也就

hiho欧拉路&#183;二 ----- Fleury算法求欧拉路径

hiho欧拉路·二 分析: 小Ho:这种简单的谜题就交给我吧! 小Hi:真的没问题么? <10分钟过去> 小Ho:啊啊啊啊啊!搞不定啊!!!骨牌数量一多就乱了. 小Hi:哎,我就知道你会遇到问题. 小Ho:小Hi快来帮帮我! 小Hi:好了,好了.让我们一起来解决这个问题. <小Hi思考了一下> 小Hi:原来是这样...小Ho你仔细观察这个例子: 因为相连的两个数字总是相同的,不妨我们只写一次,那么这个例子可以写成:3-2-4-3-5-1.6个数字刚好有5个间隙,每个间隙两边的数字由

hiho一下 第五十周 题目1 : 欧拉路&#183;二

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其实是一块一块骨牌. 主角继续往前走,面前出现了一座石桥,石桥的尽头有一道火焰墙,似乎无法通过. 小Hi注意到在桥头有一张小纸片,于是控制主角捡起了这张纸片,只见上面写着: 将M块骨牌首尾相连放置于石桥的凹糟中,即可关闭火焰墙.切记骨牌需要数字相同才能连接. ——By 无名的冒险者 小Hi和小Ho打开了主角的道具栏,发现主角恰好拥有M快骨牌. 小H

hiho一下 第四十九周 题目1 : 欧拉路&#183;一【无向图 欧拉路问题】

题目1 : 欧拉路·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho最近在玩一个解密类的游戏,他们需要控制角色在一片原始丛林里面探险,收集道具,并找到最后的宝藏.现在他们控制的角色来到了一个很大的湖边.湖上有N个小岛(编号1..N),以及连接小岛的M座木桥.每座木桥上各有一个宝箱,里面似乎装着什么道具. 湖边还有一个船夫,船夫告诉主角.他可以载着主角到任意一个岛上,并且可以从任意一个岛上再载着主角回到湖边,但是主角只有一次来回的机会.同时船夫告诉主

hiho一下 第五十周 欧拉路&#183;二

题目链接:click here~~ [题目大意] 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其实是一块一块骨牌. 主角继续往前走,面前出现了一座石桥,石桥的尽头有一道火焰墙,似乎无法通过. 小Hi注意到在桥头有一张小纸片,于是控制主角捡起了这张纸片,只见上面写着: 将M块骨牌首尾相连放置于石桥的凹糟中,即可关闭火焰墙.切记骨牌需要数字相同才能连接. --By 无名的冒险者 小Hi和小Ho打

hiho一下 第四十九周 欧拉路&#183;一

[题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho最近在玩一个解密类的游戏,他们需要控制角色在一片原始丛林里面探险,收集道具,并找到最后的宝藏.现在他们控制的角色来到了一个很大的湖边.湖上有N个小岛(编号1..N),以及连接小岛的M座木桥.每座木桥上各有一个宝箱,里面似乎装着什么道具. 湖边还有一个船夫,船夫告诉主角.他可以载着主角到任意一个岛上,并且可以从任意一个岛上再载着主角回到湖边,但是主角只有一次来回的机会

[hihoCoder] 第四十九周: 欧拉路&#183;一

题目1 : 欧拉路·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho最近在玩一个解密类的游戏,他们需要控制角色在一片原始丛林里面探险,收集道具,并找到最后的宝藏.现在他们控制的角色来到了一个很大的湖边.湖上有N个小岛(编号1..N),以及连接小岛的M座木桥.每座木桥上各有一个宝箱,里面似乎装着什么道具. 湖边还有一个船夫,船夫告诉主角.他可以载着主角到任意一个岛上,并且可以从任意一个岛上再载着主角回到湖边,但是主角只有一次来回的机会.同时船夫告诉主

欧拉路&amp;&amp;欧拉回路 概念及其练习

欧拉路: 如果给定无孤立结点图G,若存在一条路,经过图中每边一次且仅一次,这条路称为欧拉路: 如果给定无孤立结点图G,若存在一条回路,经过图中每边一次且仅一次,那么该回路称为欧拉回路. 存在欧拉回路的图,称为欧拉图. 一. 对于无向图G,具有一条欧拉路,当且仅当G是连通的,且有零个或两个奇数度结点. 且有零个奇数度结点,存在欧拉回路:有两个奇数度结点,存在欧拉路. 判断无向图G是否连通,可以从任意结点出发,进行深度优先遍历,如果可以遍历到所有点,也可以用并查集,判断根节点的个数, 说明,图G连通