状态压缩BFS poj1753 hdu5025 hdu1885

    xiaoxiao2021-03-25  92

    第一次接触 状态压缩类的题刚开始的话,完全没有思路也没有想到位运算,然后就各种gg,

    废话不说了 直接上代码吧。

    POJ 1753;

    题意就是翻棋子,求使棋盘上的棋子都是白棋或者黑棋,因为只有16个格子int的范围还能容下1<<16所以就用一个数来表示当前的状态就可以了。这里有个小技巧,就是读入的时候一重循环16如果是黑色(这里以黑色为1,白色为0)开始的状态就j加1<<i。然后bfs就可以了,记得要判断边界条件。

    补充一下位运算

    如果要获得第i位的数据,判断((data&(0X1<<i))==0),若真,为0,假,为1; 如果要设置第i位为1,data=(data|(0X1<<i)); 如果要设置第i位为0,data=(data&(~(0X1<<i))); 如果要将第i位取反,data=(data^(0X1<<i); 如果要取出一个数的最后一个1(lowbit):(data&(-data))         (这里利用的是负数取反加1实际上改变的是二进制最低位的1如果要获得第i位的数据,判断((data&(0X1<<i))==0),若真,为0,假,为1; 如果要设置第i位为1,data=(data|(0X1<<i)); 如果要设置第i位为0,data=(data&(~(0X1<<i))); 如果要将第i位取反,data=(data^(0X1<<i); 如果要取出一个数的最后一个1(lowbit):(data&(-data))         (这里利用的是负数取反加1实际上改变的是二进制最低位的1这个性质

    #include <iostream> #include<algorithm> #include<stdio.h> #include<string.h> #include<queue> using namespace std; struct node { int date; int step; }; bool book[65536],flag=0; int bfs(int st) { memset(book,0,sizeof(book)); struct node head,tail; head.date=st; head.step=0; book[st]=1; queue<node> que; que.push(head); while(!que.empty()) { head=que.front(); que.pop(); if(head.date==0||head.date==65535) { printf("%d\n",head.step); return 1; } for(int i=0;i<16;i++) { tail.date=head.date^(1<<i); if(i%4) { tail.date=tail.date^(1<<(i-1)); } if(i>3) { tail.date=tail.date^(1<<(i-4)); } if(i<12) { tail.date=tail.date^(1<<(i+4)); } if((i+1)%4) { tail.date=tail.date^(1<<(i+1)); } if(!book[tail.date]) { tail.step=head.step+1; book[tail.date]=1; que.push(tail); } } } return 0; } int main() { int st=0; for(int i=0;i<16;i++) { char c; scanf(" %c",&c); if(c=='b') { st+=1<<i; } } flag=bfs(st); if(flag==0) printf("Impossible\n"); return 0; } hdu 1885 和上道题一样就是用位运算保存 ,但是自己错了好多次。 #include <iostream> #include<algorithm> #include<stdio.h> #include<string.h> #include<queue> using namespace std; char map[120][120]; struct node { int x,y,snake,step,keys; bool friend operator <(const node &a,const node & b) { return a.step>b.step; } }; bool vis[120][120][10][(1<<5)+5]; int dir[4][2]={0,1,0,-1 ,1,0 ,-1,0}; int n,k; int sx,sy,ex,ey; int book[120][120]; bool check(int x,int y) { if(x<=0||y<=0||x>n||y>n) return 0; return 1; } int bfs() { struct node head,tail; head.x=sx;head.y=sy;head.step=0;head.keys=0;head.snake=0; vis[sx][sy][0][0]=1; priority_queue<node> que; que.push(head); while(!que.empty()) { head=que.top(); que.pop(); if(head.x==ex&&head.y==ey&&head.keys==k) { return head.step; } for(int i=0;i<4;i++) { tail.x=head.x+dir[i][0]; tail.y=head.y+dir[i][1]; tail.snake=head.snake; tail.step=head.step+1; tail.keys=head.keys; if(check(tail.x,tail.y)&&!vis[tail.x][tail.y][tail.keys][tail.snake]&&map[tail.x][tail.y]!='#') { int key=map[tail.x][tail.y]-'0'; if(tail.keys+1==key) { tail.keys+=1; vis[tail.x][tail.y][tail.keys][tail.snake]=1; que.push(tail); } else if(map[tail.x][tail.y]=='S') { if(tail.snake&(1<<book[tail.x][tail.y])) { vis[tail.x][tail.y][tail.keys][tail.snake]=1; que.push(tail); } else { tail.snake+=1<<book[tail.x][tail.y]; tail.step++; vis[tail.x][tail.y][tail.keys][tail.snake]=1; que.push(tail); } } else { vis[tail.x][tail.y][tail.keys][tail.snake]=1; que.push(tail); } } } } return -1; } int main() { while(scanf("%d%d",&n,&k)!=EOF) { if(n==0&&k==0) break; memset(vis,0,sizeof(vis)); int cnt=0,ans=-1; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf(" %c",&map[i][j]); if(map[i][j]=='T') {ex=i;ey=j;} else if(map[i][j]=='K') {sx=i;sy=j;} else if(map[i][j]=='S') { book[i][j]=cnt++;} } } ans=bfs(); if(ans!=-1) printf("%d\n",ans); else printf("impossible\n"); } return 0; } hdu 5025 这道题就是孙哥。去救师傅。用个四位vis标记,这道题的keys比较好解决,如果他碰到钥匙必须在把前面的钥匙拿齐的情况下才能捡起这个钥匙,第二个条件是蛇因为只有五个蛇所以用cnt把每个蛇标记,还有如果已经把蛇打死就不需要再打了。还有一点就是如果碰到师傅,但没有拿齐钥匙也不能救师傅。。加上优先队列优化哈。 #include <iostream> #include<algorithm> #include<stdio.h> #include<string.h> #include<queue> using namespace std; char map[120][120]; struct node { int x,y,snake,step,keys; bool friend operator <(const node &a,const node & b) { return a.step>b.step; } }; bool vis[120][120][10][(1<<5)+5]; int dir[4][2]={0,1,0,-1 ,1,0 ,-1,0}; int n,k; int sx,sy,ex,ey; int book[120][120]; bool check(int x,int y) { if(x<=0||y<=0||x>n||y>n) return 0; return 1; } int bfs() { struct node head,tail; head.x=sx;head.y=sy;head.step=0;head.keys=0;head.snake=0; vis[sx][sy][0][0]=1; priority_queue<node> que; que.push(head); while(!que.empty()) { head=que.top(); que.pop(); if(head.x==ex&&head.y==ey&&head.keys==k) { return head.step; } for(int i=0;i<4;i++) { tail.x=head.x+dir[i][0]; tail.y=head.y+dir[i][1]; tail.snake=head.snake; tail.step=head.step+1; tail.keys=head.keys; if(check(tail.x,tail.y)&&!vis[tail.x][tail.y][tail.keys][tail.snake]&&map[tail.x][tail.y]!='#') { int key=map[tail.x][tail.y]-'0'; if(tail.keys+1==key) { tail.keys+=1; vis[tail.x][tail.y][tail.keys][tail.snake]=1; que.push(tail); } else if(map[tail.x][tail.y]=='S') { if(tail.snake&(1<<book[tail.x][tail.y])) { vis[tail.x][tail.y][tail.keys][tail.snake]=1; que.push(tail); } else { tail.snake+=1<<book[tail.x][tail.y]; tail.step++; vis[tail.x][tail.y][tail.keys][tail.snake]=1; que.push(tail); } } else { vis[tail.x][tail.y][tail.keys][tail.snake]=1; que.push(tail); } } } } return -1; } int main() { while(scanf("%d%d",&n,&k)!=EOF) { if(n==0&&k==0) break; memset(vis,0,sizeof(vis)); int cnt=0,ans=-1; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf(" %c",&map[i][j]); if(map[i][j]=='T') {ex=i;ey=j;} else if(map[i][j]=='K') {sx=i;sy=j;} else if(map[i][j]=='S') { book[i][j]=cnt++;} } } ans=bfs(); if(ans!=-1) printf("%d\n",ans); else printf("impossible\n"); } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-16814.html

    最新回复(0)