POJ1768 Hang or not to hang

Language:Default

Hang or not to hang

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 871 Accepted: 226

Description

Little Tom is learning how to program. He has just written some programs but is afraid to run them, because he does not know if they will ever stop. Please write a program to help him. This task is not as easy as it may seem, because Tom's programs are possibly not deterministic. Given a program written by Tom, your program should tell him whether his program can stop and if so, what is the shortest possible time before it stops. 

Tom's computer consists of 32 1-bit registers and the program consists of n instructions. The registers are numbered from 0 to 31 and the instructions are numbered from 0 to n-1. 

Below, MEM[a] stands for the contents of the a-th register, 0 <= a, b < 32, 0 <= x < n, 0 <= c <= 1. 

The instruction set is as follows: 
 
InstructionSemantics

AND a b 
OR a b 
XOR a b 
NOT a 
MOV a b 
SET a c 
RANDOM a 
JMP x 
JZ x a 
STOP 

MEM[a] := MEM[a] and MEM[b] 
MEM[a] := MEM[a] or MEM[b] 
MEM[a] := MEM[a] xor MEM[b] 
MEM[a] := not MEM[a] 
MEM[a] := MEM[b] 
MEM[a] := c 
MEM[a] := random value (0 or 1) 
jump to the instruction with the number x 
jump to the instruction with the number x if MEM[a] = 0 
stop the program 

The last instruction of a program is always STOP (although there can be more than one STOP instruction). Every program starts with the instruction number 0. Before the start, the contents of the registers can be arbitrary values. Each instruction (including STOP) takes 1 processor cycle to execute. 
Task 
Write a program that: 

reads the program, 
computes the shortest possible running time of the program, 
writes the result. 

Input

The first line of the input contains an integer n (1 <= n <= 16) being the number of instructions of the program. Each of the next n lines contains one instruction of the program in the format given above. You may assume that the only white characters in the program are single spaces between successive tokens of each instruction.

Output

The first and only line of the output should contain the shortest possible running time of the program, measured in processor cycles. If the program cannot stop, output should contain the word HANGS.

Sample Input

5
SET 0 1
JZ 4 0
RANDOM 0
JMP 1
STOP

Sample Output

6

Source

Central Europe 2003

 

题意:给你n种命令,最多32个寄存器,问可能的最少的执行命令次数,使程序终止。

 

坑点:每个寄存器的初始值是随机的(0或者1)

 

思路:刚看到这题的时候以为每个寄存器的值为整数,毫无头绪,看大佬的博客才发现看错题意了,因为SET a c 说了c的值为0或1,所以每个寄存器的初始值为0或者1,直接把每个寄存器对应一个二进制位就行了。

JZ语句处理的话,只需要管跟a直接或间接相关的寄存器就可以了,因为总共16条语句,其中最后一条是STOP,那么去掉JZ之后还剩14条语句,说明最多有15个寄存器跟JZ有关,其他无关的寄存器就不用管了,记录一下需要管的寄存器就行,然后搜索的时候枚举二进制位寄存器的值放进队列,按照题目所给的语句进行操作就就可了。遇到random语句直接把该寄存器对应位置转换成二进制就行了。

 

顺便提供一些大佬造的数据

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define N 35
#define M 1<<15
#define inf ((1<<16)-1)
vector<int> p[N];
char ch[20][20];
int a[20],b[20],d[20],du[N],c[N];
int vis[20][M];
int n,m,tot;
typedef struct
{
    int u,v,t;
}node;
void dfs(int x)
{
    int i,j,k;
    k=p[x].size();
    for(i=0;i<k;i++)
    {
        j=p[x][i];
        if(du[j]==0)
        {
            du[j]=1;
            d[j]=tot++;
            dfs(j);
        }
    }
}
void bfs()
{
    int i,j,k,ans=-1;
    memset(vis,0,sizeof(vis));
    queue<node> q;
    node s,e;
    s.v=1;
    s.t=1;
    for(i=0;i<=(1<<tot);i++)
    {
        s.u=i;
        vis[1][i]=1;
        q.push(s);
    }
    while(!q.empty())
    {
        s=q.front();
        q.pop();
        if(s.v>n)
            continue;
        if(ch[s.v][0]=='S'&&ch[s.v][1]=='T')
        {
            ans=s.t;
            break;
        }
        if(ch[s.v][0]=='J'&&ch[s.v][1]=='M')
        {
            e.v=a[s.v]+1;
            e.u=s.u;
            e.t=s.t+1;
            if(vis[e.v][e.u]==0)
            {
                vis[e.v][e.u]=1;
                q.push(e);
            }
            continue;
        }
        if(ch[s.v][0]=='J'&&ch[s.v][1]=='Z')
        {
            k=((s.u>>(d[b[s.v]]))&1);
            if(k==0)
                e.v=a[s.v]+1;
            else
                e.v=s.v+1;
            e.u=s.u;
            e.t=s.t+1;
            if(vis[e.v][e.u]==0)
            {
                vis[e.v][e.u]=1;
                q.push(e);
            }
            continue;
        }
        if(du[a[s.v]]==0)
        {
            e.u=s.u;
            e.v=s.v+1;
            e.t=s.t+1;
            if(vis[e.v][e.u]==0)
            {
                vis[e.v][e.u]=1;
                q.push(e);
            }
            continue;
        }
        if(ch[s.v][0]=='R')
        {
            e.v=s.v+1;
            e.t=s.t+1;
            k=inf^(1<<d[a[s.v]]);
            e.u=s.u&k;
            if(vis[e.v][e.u]==0)
            {
                vis[e.v][e.u]=1;
                q.push(e);
            }
            e.u=s.u|(1<<d[a[s.v]]);
            if(vis[e.v][e.u]==0)
            {
                vis[e.v][e.u]=1;
                q.push(e);
            }
            continue;
        }
        j=((s.u>>d[a[s.v]])&1);
        k=((s.u>>d[b[s.v]])&1);
        if(ch[s.v][0]=='A')
            j=(j&k);
        if(ch[s.v][0]=='O')
            j=(j|k);
        if(ch[s.v][0]=='X')
            j=j^k;
        if(ch[s.v][0]=='N')
            j=j^1;
        if(ch[s.v][0]=='M')
            j=k;
        if(ch[s.v][0]=='S'&&ch[s.v][1]=='E')
            j=b[s.v];
        if(j==0)
        {
            j=inf^(1<<d[a[s.v]]);
            e.u=s.u&j;
        }
        else
        if(j==1)
            e.u=s.u|(1<<d[a[s.v]]);
        e.t=s.t+1;
        e.v=s.v+1;
        if(vis[e.v][e.u]==0)
        {
            vis[e.v][e.u]=1;
            q.push(e);
        }
    }
    if(ans==-1)
        printf("HANGS\n");
    else
        printf("%d\n",ans);
}
int main()
{
    int i,j,k;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=32;i++)
            p[i].clear();
        memset(du,0,sizeof(du));
        m=0;
        tot=0;
        for(i=1;i<=n;i++)
        {
            scanf(" %s",ch[i]);
            if(ch[i][0]=='S'&&ch[i][1]=='T')
                continue;
            if(ch[i][0]=='R'||ch[i][0]=='N'||(ch[i][0]=='J'&&ch[i][0]=='M'))
                scanf("%d",&a[i]);
            else
                scanf("%d%d",&a[i],&b[i]);
            if((ch[i][0]=='J'&&ch[i][1]=='M')||ch[i][0]=='S'||ch[i][0]=='N'||ch[i][0]=='R')
                continue;
            if(ch[i][0]=='J')
                c[++m]=b[i];
            else
                p[a[i]].push_back(b[i]);
        }
        for(i=1;i<=m;i++)
        if(du[c[i]]==0)
        {
            du[c[i]]=1;
            d[c[i]]=tot++;
            dfs(c[i]);
        }
        bfs();
    }
    return 0;
}
 

 

 

12
SET 0 0
SET 1 1
JZ 6 1
SET 2 1
RANDOM 1
JMP 2
SET 2 1
JZ 11 2
SET 0 1
RANDOM 2
JZ 7 2
STOP
16
SET 0 0
SET 1 0
SET 2 0
MOV 1 0
MOV 2 1
XOR 1 0
NOT 1
JZ 15 1
RANDOM 0
MOV 2 0
JZ 12 0
NOT 2
NOT 1
JZ 5 1
JMP 0
STOP
2
JZ 0 0
STOP

 

 

答案:13  18  2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值