POJ - 1392 Ouroboros Snake (欧拉回路的应用)

Description

Ouroboros is a mythical snake from ancient Egypt. It has its tail in its mouth and continously devours itself.

The Ouroboros numbers are binary numbers of 2^n bits that have the property of "generating" the whole set of numbers from 0 to 2^n - 1. The generation works as follows: given an Ouroboros number, we place its 2^n bits wrapped in a circle. Then, we can take
2^n groups of n bits starting each time with the next bit in the circle. Such circles are called Ouroboros circles for the number n. We will work only with the smallest

Ouroboros number for each n.

Example: for n = 2, there are only four Ouroboros numbers. These are 0011;0110;1100; and 1001. In this case, the smallest one is 0011. Here is the Ouroboros circle for 0011:

The table describes the function o(n;k) which calculates the k-th number in the Ouroboros circle of the smallest Ouroboros number of size n. This function is what your program should compute.

Input

The input consists of several test cases. For each test case, there will be a line containing two integers n and k (1<=n<=15; 0<=k<2^n). The end of the input file is indicated by a line containing two zeros. Don抰 process that line.

Output

For each test case, output o(n;k) on a line by itself.

Sample Input

2 0
2 1
2 2
2 3
0 0

Sample Output

0
1
3
2

题意:让你找个字典序最小的序列使得排成环旋转后取n个,最后可以取到[0-2^n)的所有数。

思路:欧拉回路的应用,首先为了找最短,所有我们希望这个数的后n-1位和下一个数的前n-1位是相同的,只有他们的头和尾不一样,所以我们有每添加一位就可以构成一个新的数,那么这两个数就能通过这位来连接,我们可以先枚举出所有的节点,然后对应产生边,我们最后要跑完所有的边且回到原点,而这就是欧拉回路了

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 1<<16;

struct Edge {
	int v, via;
	int vis;
};
vector<Edge> ve[maxn];
int path[maxn<<1];
int n, k, cnt;

void init() {
	for (int i = 0; i < maxn; i++)
		ve[i].clear();
}

void dfs(int cur) {
	for (int i = 0; i < ve[cur].size(); i++)
		if (!ve[cur][i].vis) {
			ve[cur][i].vis = 1;
			dfs(ve[cur][i].v);
			path[++cnt] = ve[cur][i].via + '0';
		}
	return;
}

int main() {
	while (scanf("%d%d", &n, &k) != EOF && n+k) {
		int len = n;
		n = (1<<(n-1)) - 1;
		init();
		Edge tmp;
		for (int i = 0; i <= n; i++) {
			int t = (i<<1) - ((i&(1<<(len-2)))<<1);
			tmp.v = t;
			tmp.via = 0;
			tmp.vis = 0;
			ve[i].push_back(tmp);
			t += 1;
			tmp.v = t;
			tmp.via = 1;
			tmp.vis = 0;
			ve[i].push_back(tmp);
		}
		cnt = -1;
		dfs(n);
		path[++cnt] = '\0';
		reverse(path, path+cnt);
		int ans = 0;
		for (int i = k, j = 1; j <= len; j++, i++)
			ans = (ans<<1) + (path[i%cnt]-'0');
		printf("%d\n", ans);
	}
	return 0;
}

POJ - 1392 Ouroboros Snake (欧拉回路的应用)

时间: 2024-08-01 23:08:24

POJ - 1392 Ouroboros Snake (欧拉回路的应用)的相关文章

POJ 1392 Ouroboros Snake (欧拉回路)

题目地址:poj1392 欧拉回路水题. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h> using nam

POJ 1392 Ouroboros Snake(数位欧拉)

题目链接:http://poj.org/problem?id=1392 题目大意:题意看的我头痛,其实跟HDU2894差不多,但是这题要求输出这条路径上第k个数,而不是输出路径. 解题思路:也跟HDU2894差不多.... 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define CLR(arr,val) memset(arr,val,sizeof(arr)) 5 using na

poj 1780 , poj 1392 欧拉回路求前后相互衔接的数字串

两道题目意思差不多 第一题是10进制 , 第二题是2进制的 都是利用欧拉回路的fleury算法来解决 因为我总是希望小的排在前面,所以我总是先将较小数加入栈,再利用另一个数组接收答案,但是这里再从栈中导出来答案要倒一下了,这一点要注意 poj 1780 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 using namespace std; 5 #define N 1000010 6 7 int

POJ - 1780 Code (欧拉回路+手写DFS)

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 severa

poj 1392 构造欧拉路遍历所有可能

http://poj.org/problem?id=1392 其实就是构造一个最小的数字序列,使得每n位都是一个数字,而且不重复 比如n=2  序列是00110   两个两个看就是00--0  01---1 11--3 10--2 先总结知识: 1.k进制下,这样的序列长度是k^n+n-1. 首先第一个数长度是n,后面k^n -1个数,每个数只需要增加一位就行了,所以是k^n+n-1. 2.最小 我开始的时候按回溯写,WA,然后把vis[ s ]=0注释掉 AC,不是很明白为什么,再做几题作总结

poj 1300 Door Man 欧拉回路

题目链接:http://poj.org/problem?id=1300 You are a butler in a large mansion. This mansion has so many rooms that they are merely referred to by number (room 0, 1, 2, 3, etc...). Your master is a particularly absent-minded lout and continually leaves door

poj 2337 &amp;&amp; zoj 1919 欧拉回路+连通性判断

题目要求按字典序排列,而且可能有重边 所以一开始就将数组从大到小排列,那么我将字符串加入链表时就会令小的不断前移,大的被挤到后面 这里有一点问题就是我一开始使用的是qsort: int cmp(const void *s1 , const void *s2){    return strcmp((char*)s1 , (char*)s2)<0;} qsort(str , n , sizeof(str[0]) , cmp) poj一直wa,试了发zoj却过了,可能是编译器原因吧,然后将字符串放入了

poj 2513 Colored Sticks 欧拉回路(字典树 +并查集)

此题中涉及三个小算法,这是一个无向图判断欧拉回路, 无向图存在欧拉回路的充要条件 一个无向图存在欧拉回路,当且仅当该图只存在0或2个奇数度数的顶点,且该图是连通图. 有向图存在欧拉回路的充要条件 一个有向图存在欧拉回路,所有顶点的入度等于出度且该图是连通图. 判断度数很简单,当时没想明白怎么判断图示连通的,其实只要判断他们的父节点的个数,只要只有一个父节点,那么此图是连通的. 字典树分配一下他们的id就好了,还有卡住的一点就是零图是欧拉图. 还有我做了一个小小的剪芝,但是没有什么效果,只减少了3

POJ 1637 混合图欧拉回路

先来复习一下混合图欧拉回路:给定一张含有单向边和双向边的图,使得每一点的入度出度相同. 首先对于有向边来说,它能贡献的入度出度是确定的,我们不予考虑.对于无向图,它可以通过改变方向来改变两端点的出入度.好的,我们不妨先将这些无向边随意定向,因为欧拉回路要求每点入度 = 出度,也就是总度数为偶数,存在奇数度点必不能有欧拉回路,所以我们先扫一遍总度数看看是否为偶数,如果是奇数我们弃疗就好. 接下来我们要尝试着修复这些无向边的方向使得度数平衡.首先细化问题到每一个点:对于点u,如果它的入度大于出度,那