开始的时候自己读完题目,知道它的目的,但是如何做,脑子里还没有一个清晰的思路。因为某种原因,我直接网上搜了别人的思路,知道了题目的思路,下午边上课边写程序,发现原来是这么简单的题目。下面是给我启发的那篇文章:
转载自:http://blog.csdn.net/zengniao/article/details/6644793
题目:http://poj.org/problem?id=1753
Flip Game题目大意是在一个4*4的棋盘上翻转棋子,翻转了一个棋子以后,他的上下左右四个方向的棋子都得跟着变色,最后使得棋盘上所有的棋子都是白色,或者都是黑色。统计要翻转的棋子的个数。分析:
1. 棋子只有黑白两色,因此如果翻转同一个棋子不能超过一次。因为翻转两次就等于没有翻。
2. 相同棋子之间的翻转顺序是不会影响最终翻转的结果的。
那么上面有16个棋子,也就是16个棋子处于两种状态,需要翻转,不需要翻转,总共有2^16次方种方案。因此采用枚举的方法就可以了。
数据结构:我们用位表示一个格子,那么4位组成一个16进制数,表示一行。用相应的位^1表示翻转,可以提前算出16种翻转的状态。如下:
const int state[16] = {0xC800, 0xE400, 0x7200, 0x3100, 0x8C80, 0x4E40, 0x2720, 0x1310, 0x08C8, 0X04E4, 0X0272, 0X0131, 0X008C, 0X004E, 0X0027, 0X0013}; //搜索采用回溯策略 #include <stdio.h> #define ONLINE void online() { #ifdef ONLINE #else freopen("1753.in", "r", stdin); freopen("1753.out","w", stdout); #endif } int map = 0; const int END1 = 0x0000; const int END2 = 0xFFFF; const int state[16] = {0xC800, 0xE400, 0x7200, 0x3100, 0x8C80, 0x4E40, 0x2720, 0x1310, 0x08C8, 0X04E4, 0X0272, 0X0131, 0X008C, 0X004E, 0X0027, 0X0013}; int result = 17; void read() { char c; for (int i=0; i < 16; i ++) { c = getchar(); //scanf("%c", &c); if (c == 'b') { map = map << 1; map =(map^1); } else if(c=='w') { map = map<<1; } else i --; } } void search( int idx, int step) { if (step >= result) { return; } if (idx >= 16) { if (map == END2 || map == END1) { if (step < result) { result = step; }//end if step }//end if map return; } search(idx+1, step); map = map ^ state[idx]; search(idx+1, step+1); map = map^state[idx]; return; } void print() { if (result >= 17) { printf("Impossible"); } else printf("%d",result); } int main() { online(); read(); search(0, 0); print(); return 0; }通过此题呢,我学到了用位存储信息,以前苏哥给我讲用位做八皇后,当时觉得很巧妙,但是自己没有吸收。
今天做了这道题,进一步发现了位存储矩阵信息的优点,不仅节省空间,还节省时间。妙~
一时兴起,还根据这个小算法做了一个小程序【360vsQQ】,很久没碰MFC了、这次的代码除了算法部分、其他的基本都是copy的以前写的【残缺棋盘】程序:
//主界面
//解
//说明书
转载于:https://www.cnblogs.com/CheeseZH/archive/2012/04/11/2443123.html
相关资源:数据结构—成绩单生成器