您的位置:首页 > 其它

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

2014-08-31 17:28 176 查看
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,不是很明白为什么,再做几题作总结

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const double EPS = 1e-8;
const int INF = 100000000;
const int MAXN = 17;
int ans[1<<MAXN],vis[1<<MAXN];

int n,k,all,num;

int dfs(int cnt,int s)
{
if(cnt == num)return 1;
for(int i=0;i<=1;i++)
{
if(!vis[((s<<1)+i)&all])
{
vis[((s<<1)+i)&all]=1;
int cc=ans[cnt];
ans[cnt]=i;
if(dfs(cnt+1, ((s<<1)+i)&all ))return 1;
//vis[(s<<1)+i]=0;///此处没注释掉的时候,WA。。。
}
}
return 0;
}

void solve()
{
int out=0;
for(int i=0;i<k;i++)
{
out<<=1;
out=(out+ans[i+n])&all;
}
printf("%d\n",out);
}

int main()
{
// IN("poj1392.txt");
while(~scanf("%d%d",&n,&k) && n+k)
{
CL(ans,0);
CL(vis,0);
num = (1<<n)+n-1;//总的位数
all = (1<<n)-1;
k%=(all+1);
vis[0]=1;
dfs(n,0);//0~n-1  -- 前n位是0,然后从n+1位开始遍历
solve();
}
return 0;
}


在网上找到了一个非递归版,贴在此膜拜下http://www.cnblogs.com/rolight/p/3863752.html

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>

using namespace std;

typedef long long LL;
const int maxn = 1 << 16;
int ans[maxn],n,k,now,lim;
int s[maxn],snow[maxn],top,spos[maxn];
bool hs[maxn];

void dfs1() {
memset(snow,0,sizeof(snow));
top = n - 1;
ans[top] = 0; snow[0] = 0; top++;
while(top < lim) {
int w = ans[top - 1];
if(snow[w] == 2) {
top--;
snow[w] = 0;
hs[w] = false;
continue;
}
for(;snow[w] < 2;snow[w]++) {
int vv = w & ((1 << (n - 1)) - 1);
vv = (vv << 1) + snow[w];
if(!hs[vv]) {
ans[top] = vv;
snow[w]++;
top++;
hs[vv] = true;
break;
}
}
}
}

bool dfs(int now) {
bool ret = false;
if(now == lim) return true;
for(int i = 0;i <= 1;i++) {
int vv = ans[now - 1] & ((1 << (n - 1)) - 1);
vv = (vv << 1) + i;
if(!hs[vv]) {
hs[vv] = true;
ans[now] = vv;
ret |= dfs(now + 1);
}
if(ret) break;
}
return ret;
}

void solve() {
for(int i = 0;i < n;i++) ans[i] = 0;
hs[0] = true;
/*
dfs(n);
*/
dfs1();
int ret = 0;
for(int i = 0;i < n;i++) {
ret = ret << 1;
ret += ans[(k + i) % (1 << n)] % 2;
}
printf("%d\n",ret);
}

int main() {
while(scanf("%d%d",&n,&k),n) {
memset(hs,0,sizeof(hs));
now = 0;
lim = (1 << n) + n - 1;
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: