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*/ //这很奇怪,为什么不一样呢,初始化都弄好了啊





原创粉丝点击