您的位置:首页 > 其它

状态压缩+枚举 POJ 3279 Fliptile

2015-08-02 13:24 381 查看
题目传送门

 /*
题意:问最少翻转几次使得棋子都变白,输出翻转的位置
状态压缩+枚举:和之前UVA_11464差不多,枚举第一行,可以从上一行的状态知道当前是否必须翻转
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 20;
const int INF = 0x3f3f3f3f;
int a[MAXN][MAXN];
int b[MAXN][MAXN];
int ans[MAXN][MAXN];
int dx[5] = {-1, 0, 0, 0, 1};
int dy[5] = {0, 1, 0, -1, 0};
int n, m;

int get_col(int x, int y)   {
int ret = a[x][y];
for (int i=0; i<5; ++i) {
int tx = x + dx[i], ty = y + dy[i];
if (tx < 0 || tx >= n || ty < 0 || ty >= m) continue;
ret += b[tx][ty];
}
return ret & 1;
}

int check(int s)    {
memset (b, 0, sizeof (b));
for (int i=0; i<m; ++i) {
if (s & (1 << i))   b[0][i] = 1;
}
for (int i=1; i<n; ++i) {
for (int j=0; j<m; ++j) {
if (get_col (i-1, j))   b[i][j] = 1;
}
}
for (int i=0; i<m; ++i) if (get_col (n-1, i))   return INF;
int ret = 0;
for (int i=0; i<n; ++i) {
for (int j=0; j<m; ++j) ret += b[i][j];
}
return ret;
}

int main(void)  {       //POJ 3279 Fliptile
while (scanf ("%d%d", &n, &m) == 2) {
for (int i=0; i<n; ++i)    {
for (int j=0; j<m; ++j)    {
scanf ("%d", &a[i][j]);
}
}
int mn = INF;
memset (ans, 0, sizeof (ans));
for (int i=0; i<(1<<m); ++i)    {
int res = check (i);
if (res < mn)   {
mn = res;
for (int i=0; i<n; ++i)    {
for (int j=0; j<m; ++j)    {
if (b[i][j])    ans[i][j] = 1;
else    ans[i][j] = 0;
}
}
}
}
if (mn < INF)   {
for (int i=0; i<n; ++i)    {
for (int j=0; j<m; ++j)    printf ("%d%c", ans[i][j], (j == m-1) ? '\n' : ' ');
}
}
else    puts ("IMPOSSIBLE");
}

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