poj 1768 Hang or not to hang 离散化+搜索+状态压缩
来源:互联网 发布:手机怎么样开淘宝店 编辑:程序博客网 时间:2024/06/10 10:48
题目链接:
http://poj.org/problem?id=1768
题目意思:
给你n种命令,最多32个寄存器,问可能的最少的执行命令次数,使程序终止。
解题思路:
对于不能直接和间接影响JZ中的寄存器的寄存器的状态可以是任意,因为他们每一步都是确定的,最终命令执行的次数与初始状态无关。
所以先找出直接和间接影响JZ中的寄存器的寄存器,由于命令最多只有16个,所以除去STOP和JZ,最多只有14个命令,影响的寄存器最多只有16个。
比如命令 AND a b 则寄存器b能影响a,则将a连一条有向边到b.
建好图后,从JZ中的寄存器出发,用dfs扫一遍,得到的寄存器全部是能影响JZ寄存器的,将这些寄存器离散化处理,得到最多16个寄存器,然后状态压缩,每一位表示一个寄存器。枚举初始化的寄存器的状态。
判断程序能否终止,主要看当前命令下的寄存器状态是否处理过,如果处理过,则程序陷入死循环,不能终止。
遇到无用状态直接跳过,因为他们不影响主要寄存器的状态。
代码:
#include<iostream>#include<cmath>#include<cstdio>#include<cstdlib>#include<string>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#define eps 1e-6#define INF 0x1f1f1f1f#define PI acos(-1.0)#define ll __int64#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1using namespace std;/*freopen("data.in","r",stdin);freopen("data.out","w",stdout);*/bool vis[16][1<<15],vv[32]; //映射后只有这么多的寄存器能影响int map1[32]; //将状态映射过来char save[16][10]; //保存命令int can1[16],can2[16],n,m,ans,ss; //参数vector<int>jz;vector<int>hav[32];int bin[40]; //将每一个寄存器对应的值保存下来int cal(char * a) //返回该命令的参数个数{ if(!strcmp(a,"NOT")||!strcmp(a,"RANDOM")||!strcmp(a,"JMP")) return 1; if(!strcmp(a,"STOP")) return 0; return 2;}void dfs(int cur){ for(int i=0;i<hav[cur].size();i++) { if(vv[hav[cur][i]]) continue; //printf("cur:%d->%d\n",cur,hav[cur][i]); vv[hav[cur][i]]=true; map1[hav[cur][i]]=m; m++; dfs(hav[cur][i]); } return ;}void Dfs(int sta,int i,int ss){ if(i>=n) return ; if(vis[i][sta]) return ; ss++; vis[i][sta]=true; int T=sta; if(!strcmp(*(save+i),"AND")) { int a=map1[can1[i]],b=map1[can2[i]]; //取出对应的离散化的位置 if(a==-1||b==-1) //遇到无效状态,直接跳过 { Dfs(sta,i+1,ss); vis[i][sta]=false; //从前往后就不用回溯,因为后面的情况一定比当前坏 return ; } int tt=sta; int aa=(tt>>a)&1,bb=(tt>>b)&1; //取出两寄存器的数 if(aa&bb) //运算,并把结果加进去 tt=tt|bin[a]; else tt=tt-(aa<<a); Dfs(tt,i+1,ss); } else if(!strcmp(*(save+i),"OR")) { int a=map1[can1[i]],b=map1[can2[i]]; //取出对应的离散化的位置 if(a==-1||b==-1) { Dfs(sta,i+1,ss); vis[i][sta]=false; return ; } int tt=sta; int aa=(tt>>a)&1,bb=(tt>>b)&1; if(aa|bb) tt=tt|bin[a]; else tt=tt-(aa<<a); Dfs(tt,i+1,ss); } else if(!strcmp(*(save+i),"XOR")) { int a=map1[can1[i]],b=map1[can2[i]]; //取出对应的离散化的位置 if(a==-1||b==-1) { Dfs(sta,i+1,ss); vis[i][sta]=false; return ; } int tt=sta; int aa=(tt>>a)&1,bb=(tt>>b)&1; if(aa^bb) tt=tt|bin[a]; else tt=tt-(aa<<a); Dfs(tt,i+1,ss); } else if(!strcmp(*(save+i),"NOT")) { int a=map1[can1[i]]; if(a==-1) { Dfs(sta,i+1,ss); vis[i][sta]=false; return ; } sta=sta^bin[a]; //取反 Dfs(sta,i+1,ss); } else if(!strcmp(*(save+i),"MOV")) { int a=map1[can1[i]],b=map1[can2[i]]; if(a==-1||b==-1) { Dfs(sta,i+1,ss); vis[i][sta]=false; return ; } int aa=(sta>>b)&1; if(aa) sta=sta|bin[a]; else sta=sta&((bin[m]-1)-bin[a]); //把第a个寄存器清零 Dfs(sta,i+1,ss); // vis[i][sta]=true; } else if(!strcmp(*(save+i),"SET")) { int a=map1[can1[i]],b=can2[i]; if(a==-1) { Dfs(sta,i+1,ss); vis[i][sta]=false; return ; } if(b) sta=sta|(1<<a); else sta=sta&((bin[m]-1)-bin[a]); Dfs(sta,i+1,ss); // vis[i][sta]=true; } else if(!strcmp(*(save+i),"JMP")) { int a=can1[i]; Dfs(sta,a,ss); } else if(!strcmp(*(save+i),"JZ")) { int a=can1[i],b=map1[can2[i]]; int bb=(sta>>b)&1; //一定是影响寄存器 if(!bb) { Dfs(sta,a,ss); vis[i][sta]=false; return ; } Dfs(sta,i+1,ss); } else if(!strcmp(*(save+i),"STOP")) { if(ss<ans) ans=ss; } else if(!strcmp(*(save+i),"RANDOM")) { int a=map1[can1[i]]; if(a==-1) { Dfs(sta,i+1,ss); vis[i][sta]=false; return ; } Dfs(sta|bin[a],i+1,ss); //置1 Dfs(sta&(bin[m]-1-bin[a]),i+1,ss); //置0 } vis[i][T]=false;}int main(){ //printf("%d\n",((1<<31)-1)); for(int i=0;i<=35;i++) bin[i]=(1<<i); while(scanf("%d",&n)!=EOF) { memset(map1,-1,sizeof(map1)); memset(vv,false,sizeof(vv)); jz.clear(); for(int i=0;i<32;i++) hav[i].clear(); for(int i=0;i<n;i++) { scanf("%s",save+i); int t=cal(*(save+i)); if(t==1) scanf("%d",&can1[i]); else if(t==2) { scanf("%d%d",&can1[i],&can2[i]); if(!strcmp(*(save+i),"JZ")) { jz.push_back(can2[i]); //从这点开始扫描有影响的状态 continue; } if(strcmp(*(save+i),"SET")) //set命令不影响 hav[can1[i]].push_back(can2[i]); //寄存器2能影响寄存器1 } } m=0; //有效的寄存器,能影响的 for(int i=0;i<jz.size();i++) //反向扫描能影响的所有寄存器 { if(!vv[jz[i]]) { map1[jz[i]]=m; m++; vv[jz[i]]=true; dfs(jz[i]); } } // printf("m:%d\n",m); ans=INF; memset(vis,false,sizeof(vis)); /* for(int i=bin[m]-1;i>=0;i--) //枚举初始状态 Dfs(i,0,0); //从第0步开始执行*/ //这样写要回溯 for(int i=0;i<=bin[m]-1;i++) Dfs(i,0,0); //这样写不用回溯 //for(int i=0;i<) if(ans==INF) printf("HANGS\n"); else printf("%d\n",ans); } return 0;}/*4AND 0 1JZ 1 0RANDOM 1STOP1AND 0 14SET 0 1SET 1 1NOT 1STOP2JMP 1JMP 05RANDOM 0JZ 4 0ADD 0 1ADD 0 2STOP3SET 0 1RANDOM 0RANDOM 111XOR 0 2SET 0 0NOT 0JZ 5 0JMP 2AND 1 3SET 1 1JZ 10 1RANDOM 1JMP 7STOP5SET 0 1JZ 4 0RANDOM 0JMP 1STOPans:HANGSans:14ans:63RANDOM 0AND 1 0STOPHANGS*//*1AND 0 1m:0HANGS3RANDOM 0AND 1 2STOPm:031AND 0 1m:03*/ //这很奇怪,为什么不一样呢,初始化都弄好了啊
- poj 1768 Hang or not to hang 离散化+搜索+状态压缩
- poj 1768 Hang or not to hang 离散化+二进制状态压缩+枚举初始状态+搜索 (两种做法 bfs dfs 都能过)
- POJ-1768:Hang or not to hang(bfs+一些特殊优化)
- ZOJ 1639 Hang Up the System (状态压缩)
- hdu4628 状态压缩搜索or状态dp
- No Response from the Server, Does it Hang or Spin?
- fix system hang when thumbnail or playback interlace clips(转载)
- poj 1088 dp记忆化搜索状态( or dfs)
- poj 1143 Number Game 博弈 记忆化状态压缩搜索
- POJ 1351 Number of Locks (记忆化搜索 状态压缩)
- POJ 2046 Gap 搜索- 状态压缩
- Hang loose 轻松自如
- GoAhead Web Server Hang
- JOJ1082: Hang Over
- IE hang 分析
- ZOJ1045 Hang Over
- Oracle数据库的Hang
- Hang File Generator
- 常用Windows消息、常量命名参考
- AJAX判断用户是否已注册
- linux系统2440开发板域名解析问题
- ibatis与hibernate有什么区别啊?
- Redis命令总结
- poj 1768 Hang or not to hang 离散化+搜索+状态压缩
- uva10617 - Again Palindrome(动归)
- C++异常
- 不得不聊的关于方法的参数的那些事儿
- 常用Windows消息、常量命名参考
- 查询所有数据库数据文件的SQL
- 常用Windows消息、常量命名参考
- (转载)cocos2d-X学习之引擎源码目录结构介绍
- 我想买一个带vxworks的arm,哪位高手能推荐一下呀?万分感谢!