Flip Game---poj1753(状压+bfs)
题目链接:http://poj.org/problem?id=1753
题意:是有一个4X4的图,b代表黑色,w代表白色,问最少翻转几次可以把所有的点变成白色或者黑色,每次翻转一个点时,可以把它周围的上下左右都给翻转;
一共16个棋子,假设开始时都是0,即0000 0000 0000 0000 当翻转第一行第一列时,会变成1100 1000 0000 0000(2) = 51200(10) 所以,一共有16种状态,我们可以把它列出来如下代码中的 t 数组;
剩下的就是用bfs搜索所有状态即可;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<stdio.h> #include<string.h> #include<string> #include<vector> #include<algorithm> #include<map> #include<queue> using namespace std; #define met(a, b) memset(a, b, sizeof(a)) #define N 101 typedef long long LL; int t[20] = { 51200, 58368, 29184, 12544, 35968, 20032, 10016, 4880 , 2248 , 1252 , 626 , 305 , 140 , 78 , 39 , 19 , }; int vis[1<<16]; struct node { int x, step; node(){} node(int x, int step):x(x), step(step){} }; int bfs(int s) { queue<node> Q; Q.push(node(s, 0)); met(vis, 0); vis[s] = 1; while(Q.size()) { node p = Q.front(), q; Q.pop(); if(p.x == (1<<16)-1 || p.x == 0) return p.step; for(int i=0; i<16; i++) { q.step = p.step + 1; q.x = p.x^t[i];///p状态的下一状态q; if(vis[q.x] == 0) { vis[q.x] = 1; Q.push(q); } } } return -1; } int main() { int cnt = 15, start = 0; for(int i=0; i<4; i++) { char s[10]; scanf("%s", s); for(int j=0; j<4; j++) { if(s[j] == 'w') start |= (1<<cnt);///计算起始状态,|相当于做加法; cnt--; } } int ans = bfs(start); if(ans == -1) puts("Impossible"); else printf("%d\n", ans); return 0; }