您的位置:首页 > 其它

Flip Game---poj1753(状压+bfs)

2016-08-01 08:49 274 查看
题目链接: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搜索所有状态即可;

#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;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: