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,不是很明白为什么,再做几题作总结
在网上找到了一个非递归版,贴在此膜拜下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;
}
其实就是构造一个最小的数字序列,使得每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;
}
相关文章推荐
- DFS 遍历数组所有可能存在的出栈顺序
- POJ 2155 二维线段树 经典的记录所有修改再统一遍历 单点查询
- poj 2778 DNA Sequence AC自动机+DP+矩阵乘法 检测所有可能的n位DNA串有多少个DNA串中不含有指定的病毒片段
- poj2255~~Tree Recovery (树的遍历构造~)
- 给定二叉树的前序遍历结果,输出所有可能的中序遍历的结果
- POJ 1270 Following Orders(拓扑排序:输出所有可能)
- POJ 1125 可不可能遍历所有点情况下的最短路径
- POJ 1270 Following Orders(拓扑排序:输出所有可能)
- poj 2404 Jogging Trails 求走最少距离使得所有边至少都遍历一次并回到原点(即sum+加上最少多少距离使得原图变成欧拉回路) FLOYD+状态压缩DP
- POJ 2752 (KMP 所有可能长度的前缀后缀) Seek the Name, Seek the Fame
- 再谈如何遍历Asp.net窗体下所有的控件
- 遍历XML文档的所有节点及属性(ASP)
- 如何用foreach遍历页面上所有的TextBox,判断他们是否为空?
- 如何用foreach遍历页面上所有的TextBox(转载)
- 用拓扑排序+动态规划的方法输出DAG的所有可能的路径
- 如何遍历页面中的所有单行输入框对象
- 如何用foreach遍历页面上所有的TextBox(转载)
- 遍历该文件夹下的所有文件并生成xml树
- 如何在ASP.NET下遍历指定页面上所有控件
- [原创]递归应用-遍历所有下层分类