Description

Input
Output
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 (欧拉回路的应用),布布扣,bubuko.com
POJ - 1392 Ouroboros Snake (欧拉回路的应用)
原文:http://blog.csdn.net/u011345136/article/details/38454177