标签:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 37050 | Accepted: 16122 |
Description
Input
Output
Sample Input
bwwb bbwb bwwb bwww
Sample Output
4
没点思路-_-
转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1299076400
提示:翻转棋,可以建模为多叉树
本题难点有两个,一个就是不要以全黑(或全白)作为目标进行搜索,而是要把全黑(或全白)作为“根”,去搜索树叶,看看是否有 输入的棋盘状态。
另一个难点需要一点数学功底,就是要知道 树 的最大高度,这是“状态不存在”的判断标准
提示:其实每格棋子最多只可以翻转一次(实际是奇数次,但这没意义),只要其中一格重复翻了2次(不论是连续翻动还是不连翻动),那么它以及周边的棋子和没翻动时的状态是一致的,由此就可以确定这个棋盘最多只能走16步,最多只能有翻出2^16种状态
其实也想过dfs,找不到终止状态,对,就是16就ok了,因为如果每一个状态都翻转了一遍,那么你在翻转一个牌,那么就和他之前没翻转是一样的,所以没必要了
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; bool chess[10][10]; int step,flag; int r[4] = {-1,1,0,0}; int c[4] = {0,0,-1,1}; int judge_all() { for(int i = 1; i <= 4; i++) { for(int j = 1; j <= 4; j++) { if(chess[i][j] != chess[1][1]) return false; } } return true; } void flip(int row, int col) { chess[row][col] = !chess[row][col]; for(int i = 0; i < 4; i++) { int fx = row + r[i]; int fy = col + c[i]; if(fx > 0 && fx <= 4 && fy > 0 && fy <= 4) chess[fx][fy] = !chess[fx][fy]; } } void dfs(int row, int col, int deep) { if(deep == step) // 到达了翻转的指定次数,就判断是否都一样,然后返回 { flag = judge_all(); return; } if(flag || row > 4) return; flip(row, col); if(col < 4) { dfs(row, col + 1, deep + 1); //如果这一行还可以翻转,就判断下一个 } else { dfs(row + 1, 1, deep + 1); } flip(row, col); //回溯,把原来的转过来 if(col < 4) { dfs(row, col + 1, deep); //回溯时要判断上一步是否已经结束,因此传的是deep,判断当前状态,如果没结束,就按row,col+1变化 } else { dfs(row + 1, 1, deep); } return; } int main() { char s[10]; while(scanf("%s", s) != EOF) { memset(chess, false, sizeof(chess)); for(int i = 0; i < 4; i++) { if(s[i] == ‘b‘) { chess[1][i + 1] = true; } } for(int i = 2; i <= 4; i++) { scanf("%s", s); for(int j = 0; j < 4; j++) { if(s[j] == ‘b‘) chess[i][j + 1] = true; } } flag = 0; for(step = 0; step <= 16; step++) { dfs(1,1,0); if(flag) break; } if(flag) printf("%d\n", step); else printf("Impossible\n"); } return 0; }
标签:
原文地址:http://www.cnblogs.com/zhaopAC/p/5164966.html