hdu3278 Puzzle

来源:互联网 发布:simpson算法流程图 编辑:程序博客网 时间:2024/05/18 03:33

最近在做搜索类题目,用bfs一连水了4道题,碰上Puzzle这道题时,明知道应该可以转化成bfs的,可是却怎么也找不到思路。。。

题目链接点击打开链接

题意:给定一个4*6的网格,其中有black, white, grey三种颜色,求使中间8个格子为同种颜色需要的最少操作数。

            可执行的操作有:选取某一行或某一列进行左右移或上下移,每次只能移动一位;

                                            对于一行,只能左右移;对于一列,只能上下移。

刚开始一直理解成了将一行整体上下移动,可是怎么移都和样例对不上,这才发现自己理解错了。可是即便知道如何移动,也还是不知道如何bfs。

1 状态压缩的方法是看了大牛的博客才恍然大悟的,24位是完全可以用一个int来保存的;

2 当选定其中一种颜色为中间色时,另外两种颜色已经无区别了,可以用1来表示选定色,用0来表示另外两种颜色;

3 从初始状态到最终状态的步数和从最终状态到初始状态的步数是相同的,于是我们可以倒推;

4 最终状态只有1种:中间8格为1,其余为0;

5 初始状态可有三种表示:黑色为1, 白色为1, 灰色为1;

5 从最终状态开始推,从一个状态到达另一个状态可执行4*2+6*2=20中操作,保存每一个可到达的状态,并保存其对应的步数;

6 最终选取从到达三种初始状态的步数中最小的一个。


附代码

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <iostream>#include <algorithm>#include <queue>#include <set>#define N 10using namespace std;// treat the end state as the initial state 000000 011110 011110 000000: // 2^7+2^8+2^9+2^10+2^13+2^14+2^15+2^16=124800char s[5][7],str[25];char v[1<<24];queue<int> que;int inline row_op(int r,int n,int op)   //op=1,shift left; op=0,shift right{int tmp[6];for(int i=0;i<6;i++){tmp[i]=n&(1<<(r*6+i));n-=tmp[i];}if(op){ // lefttmp[0]<<=5;for(int i=1;i<6;i++){tmp[i]>>=1;}}else{  // rightfor(int i=0;i<5;i++){tmp[i]<<=1;}tmp[5]>>=5;}n+=tmp[0]+tmp[1]+tmp[2]+tmp[3]+tmp[4]+tmp[5];return n;}int inline col_op(int c,int n,int op)   //op=1, shift up ; op=0, shift down{int tmp[4];for(int i=0;i<4;i++){tmp[i]=n&(1<<(i*6+c));   // get the bit in row i, column cn-=tmp[i];}if(op){tmp[0]<<=18;tmp[1]>>=6;tmp[2]>>=6;tmp[3]>>=6;}else{    tmp[0]<<=6;    tmp[1]<<=6;    tmp[2]<<=6;    tmp[3]>>=18;}n+=tmp[0]+tmp[1]+tmp[2]+tmp[3];return n;}// state compressionvoid countMoves(){int cnt=0;while(!que.empty()) que.pop();memset(v,-1,sizeof(v)); que.push(124800);v[124800]=0;while(!que.empty()){int t=que.front();que.pop();// row operationsfor(int i=0;i<4;i++){int tmp=row_op(i,t,1);if(v[tmp]==-1){que.push(tmp);v[tmp]=v[t]+1;}tmp=row_op(i,t,0);if(v[tmp]==-1){que.push(tmp);v[tmp]=v[t]+1;}}// column operationsfor(int j=0;j<6;j++){int tmp=col_op(j,t,1);if(v[tmp]==-1){que.push(tmp);v[tmp]=v[t]+1;}tmp=col_op(j,t,0);if(v[tmp]==-1){que.push(tmp);v[tmp]=v[t]+1;}}}return;}int main(){int T,cas=1;int b,w,g;cin >> T;countMoves();while(T--){b=w=g=0;for(int i=0;i<4;i++){scanf("%s",s[i]);for(int j=0;j<6;j++){if(s[i][j]=='B'){b+=(1<<(i*6+j));}else if(s[i][j]=='W'){w+=(1<<(i*6+j));}else{g+=(1<<(i*6+j));}}}int cnt = min(v[b],min(v[w],v[g]));cout << "Case " << cas << ": " << cnt << endl;cas++;}return 0;}



0 0
原创粉丝点击