题意: 给一个4X6的矩形,有white ,blank , grey 三种颜色各有8个格子 ,给定一个初始状态,求用最少的操作次数将图形变化为中间的8个格子颜色相同。
分析:话说,因为做过了hdu1667,一开始真的以为IDA*稳过的,敲完之后,直接TLE了,实在不解啊,原来是有测试数据的量太大了。
按照大牛的思路是这样的:当我们确定了要将中间转成什么颜色之后,转的时候发现,另外俩种颜色也就没必要区分了,所以也就可以看成是只有俩种颜色了,之后用24个位保存状态,用BFS预处理从最终状态到每一个状态需要的最小步数。最后再根据所给的图,判断将哪种颜色转到中间的步数最少即可。
虽然知道是这样的思路之后,还是一直TLE了,原来下面这俩种状态转换模式速度差那么多,ORZ
inline unsigned int changetostate() { unsigned int t=0; for(int i=0;i<4;i++) for(int j=0;j<6;j++) { t<<=1; t+=(map[i][j]-'0'); } return t; } inline void changetomap(unsigned int t) { for(int i=3;i>=0;i--) for(int j=5;j>=0;j--) { map[i][j]= (t&1)+'0'; t>>=1; } }
下面这种比较慢,改成那么那种就过了,1200+ms
inline unsigned int changetostate() { unsigned int t=0; int i,j; for(int k=0;k<24;k++) { i=k/6;j=k%6; if(map[i][j]=='1') t|=(1<<k); } return t; } inline void changetomap(unsigned int t) { int i,j; for(int k=0;k<24;k++) { i=k/6;j=k%6; if(t&(1<<k)) map[i][j]='1'; else map[i][j]='0'; } }
看整个代码吧:
#include<iostream> #include<algorithm> #include<queue> using namespace std; char step[1<<24]; char map[5][7]; char hash1[3]={'B','G','W'}; void init() { for(int i=0;i<4;i++) for(int j=0;j<6;j++) map[i][j]='0'; for(int i=1;i<3;i++) for(int j=1;j<5;j++) map[i][j]='1'; memset(step,-1,sizeof(step)); } inline unsigned int changetostate() { unsigned int t=0; for(int i=0;i<4;i++) for(int j=0;j<6;j++) { t<<=1; t+=(map[i][j]-'0'); } return t; } inline void changetomap(unsigned int t) { for(int i=3;i>=0;i--) for(int j=5;j>=0;j--) { map[i][j]= (t&1)+'0'; t>>=1; } } inline void TurnL(int x) { char c=map[x][0]; for(int i=0;i<5;i++) map[x][i]=map[x][i+1]; map[x][5]=c; } inline void TurnR(int x) { char c=map[x][5]; for(int i=5;i>=1;i--) map[x][i]=map[x][i-1]; map[x][0]=c; } inline void TurnU(int x) { char c=map[0][x]; for(int i=0;i<3;i++) map[i][x]=map[i+1][x]; map[3][x]=c; } inline void TurnD(int x) { char c=map[3][x]; for(int i=3;i>=1;i--) map[i][x]=map[i-1][x]; map[0][x]=c; } void BFS(unsigned int f) { queue<unsigned int> Q; Q.push(f); step[f]=0; unsigned int temp; unsigned int t=0; while(!Q.empty()) { temp=Q.front(); Q.pop(); changetomap(temp); for(int i=0;i<6;i++) { TurnU(i); t=changetostate(); if(step[t]==-1) { Q.push(t); step[t]=step[temp]+1; } TurnD(i); TurnD(i); t=changetostate(); if(step[t]==-1) { Q.push(t); step[t]=step[temp]+1; } TurnU(i); } for(int i=0;i<4;i++) { TurnR(i); t=changetostate(); if(step[t]==-1) { Q.push(t); step[t]=step[temp]+1; } TurnL(i); TurnL(i); t=changetostate(); if(step[t]==-1) { Q.push(t); step[t]=step[temp]+1; } TurnR(i); } } } int main() { int cas=0,T; init(); BFS(changetostate()); scanf("%d",&T); while(T--) { for(int i=0;i<4;i++) scanf("%s",map[i]); printf("Case %d: ",++cas); int ans=INT_MAX; unsigned int t; for(int i=0;i<3;i++) { t=0; for(int j=0;j<4;j++) for(int k=0;k<6;k++) { t<<=1; if(map[j][k]==hash1[i]) t+=1; } if(ans>step[t]) ans=step[t]; } printf("%d\n",ans); } return 0; }