poj_1735_Flip Game
来源:互联网 发布:微信中淘宝链接打不开 编辑:程序博客网 时间:2024/05/18 08:08
一道需要活跃思维的搜索题,当然,对于2^16 的复杂度也可以枚举来做.
题目大意: http://poj.grids.cn/practice/1753/
给一个4*4的棋盘,上面有黑子 (用字符'b'表示) 和白子 (用字符'w'表示) .可以选择棋子翻转,每翻转一个棋子,其周围四个棋子也会被翻转(边角情况正常处理),问最少翻转多少次可以让棋盘全黑或全白.
解题思路:
一看只有16个格子,首先想到了枚举~:
for(int i=0;i<1;++i)
.
.
.
16层......后来一想这么写多丢人......所以还是搜索吧,bfs和dfs基本都没有问题,因为求最少步数,所以还是bfs比较适合.
把棋盘看做简单的0-1矩阵,对每一个位置取反时也会对周围4个位置取反,对一个数取反可以写做: n=n^1; .那么从什么状态开始搜素呢?~
将0-1矩阵合并,看成一个二进制数,那么他的范围仅仅为 0-0xffff 也就是一共仅有 0xfff 种状态.对每一位翻转,可以求出其状态转移方程:
当前状态a ^ 转移状态i (i为翻转的位置),a==0 时结束,每个位置会有其单独的翻转状态.比如 0,0 位:
1100 1000 0000 0000 周围四个位置取反.
接下来就是么每一位的转移状态i的处理. 将矩阵每一位编号.
F E D C B A 9 8 7 6 5 4 3 2 1 0
那么,其上下左右就为: 上: -4 下:+4 左:-1 右: +1 求转移状态的源码就为:
void build() { memset(no,0,sizeof(no)); int num=1; for(int i=N;i>0;--i) { for(int j=1;j<=4;++j) { int tx=i*4-j; no[num]=1<<(tx); for(int k=0;k<4;++k) { int x=tx+dbit[k]; if(x<0||x>15) continue; if((tx+4)%4==0&&(x+4)%4==3) { continue; } if((tx+4)%4==3&&(x+4)%4==0) { continue; } no[num]=no[num]+(1<<x); } num++; } } }
求出转移状态后,就以每一个点为起点bfs 即可:
#include <myhead.h> const int N=4; const int s=0xffff; const int t=0; const int dbit[]={-4,1,+4,-1}; struct Node { int m,num; int i; }; bool _hash[100000]; char a[N+1][N+1]; int no[20]; Node node; void build() { memset(no,0,sizeof(no)); int num=1; for(int i=N;i>0;--i) { for(int j=1;j<=4;++j) { int tx=i*4-j; no[num]=1<<(tx); for(int k=0;k<4;++k) { int x=tx+dbit[k]; if(x<0||x>15) continue; if((tx+4)%4==0&&(x+4)%4==3) { continue; } if((tx+4)%4==3&&(x+4)%4==0) { continue; } no[num]=no[num]+(1<<x); } num++; } } } bool init() { for(int i=0;i<N;++i) { if(scanf("%s",a[i])==EOF) { return false; } } memset(_hash,0,sizeof(_hash)); node.i=node.m=node.num=0; int m=0; for(int i=N-1;i>=0;--i) { for(int j=N-1;j>=0;--j) { if(a[i][j]=='b') { node.m=node.m+(1<<m); } m=m+1; } } return true; } void bfs() { queue<Node> q; q.push(node); while(!q.empty()) { Node tmp=q.front(); q.pop(); if(tmp.m==s||tmp.m==0) { printf("%d\n",tmp.num); return ; } node.num=tmp.num+1; for(int i=1;i<=16;++i) { if(tmp.i!=i) { node.i=i; node.m=(tmp.m^no[i]); if(!_hash[node.m]) { _hash[node.m]=true; q.push(node); } } } } printf("Impossible"); } int main() { build(); init(); bfs(); return 0; }
- poj_1735_Flip Game
- game
- game
- game
- game...
- Game
- Game
- Game
- Game
- game
- Game
- Game
- game
- game
- Game
- GAME
- Game
- Game
- 一个简单但详细的解释Windows文件映射读取数据文件的例子
- 类
- js正则表达式
- MySql学习
- 键盘键码值
- poj_1735_Flip Game
- 十大畅销【编程类】书籍,买过几本呢
- eclipse新建dynamic Web project项目
- 驱动工程师不要成为了配置工程师
- C++基础注意事项
- Android平台开源voip的编译
- iOS 5中的ARC和strong和weak关键字
- 动态链接和静态链接
- Hadoop 性能调优 重要参数设置技巧