POJ 3279 Fliptile(枚举状态)
2014-12-19 23:58
344 查看
题目链接:poj.org/problem?id=3279
题意:黑白的板,每次选择一个十字形翻转(十字板内黑白互换,若是边界则不管),求最小将原图变为全白的策略。
思路:如果第一行的翻转转态能够确定,那么就可以依次往下判断其他行是否需要翻转了,所以可以枚举第一行的状态,第一行翻转方式为2^N种,故时间复杂度为O(2 ^ N* M *N)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 30;
int dx[5] = { -1, 0, 0, 0, 1};
int dy[5] = {0, -1, 0, 1, 0};
int m, n;
int opt[maxn][maxn];
int flip[maxn][maxn];
int tile[maxn][maxn];
int get(int x, int y)
{
int c = tile[x][y];
for (int i = 0; i < 5; i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && nx < m && ny >= 0 && ny < n)
c += flip[nx][ny];
}
return c % 2;
}
int cal()
{
for (int i = 1; i < m; i++)
for (int j = 0; j < n; j++)
{
if (get(i - 1, j))
flip[i][j] = 1;
}
for (int j = 0; j < n; j++)
{
if (get(m - 1, j))
return -1;
}
int res = 0;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
res += flip[i][j];
return res;
}
void solve()
{
int res = -1;
for (int i = 0; i < 1 << n; i++)
{
memset(flip, 0, sizeof(flip));
for (int j = 0; j < n; j++)
flip[0][n - 1 - j] = i >> j & 1;
int num = cal();
if (num >= 0 && (res < 0 || res > num))
{
res = num;
memcpy(opt, flip, sizeof(flip));
}
}
if (res < 0)
puts("IMPOSSIBLE");
else
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
printf("%d%c", opt[i][j], j == n - 1 ? '\n' : ' ');
}
}
}
int main()
{
while (cin >> m >> n)
{
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
cin >> tile[i][j];
solve();
}
return 0;
}
题意:黑白的板,每次选择一个十字形翻转(十字板内黑白互换,若是边界则不管),求最小将原图变为全白的策略。
思路:如果第一行的翻转转态能够确定,那么就可以依次往下判断其他行是否需要翻转了,所以可以枚举第一行的状态,第一行翻转方式为2^N种,故时间复杂度为O(2 ^ N* M *N)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 30;
int dx[5] = { -1, 0, 0, 0, 1};
int dy[5] = {0, -1, 0, 1, 0};
int m, n;
int opt[maxn][maxn];
int flip[maxn][maxn];
int tile[maxn][maxn];
int get(int x, int y)
{
int c = tile[x][y];
for (int i = 0; i < 5; i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && nx < m && ny >= 0 && ny < n)
c += flip[nx][ny];
}
return c % 2;
}
int cal()
{
for (int i = 1; i < m; i++)
for (int j = 0; j < n; j++)
{
if (get(i - 1, j))
flip[i][j] = 1;
}
for (int j = 0; j < n; j++)
{
if (get(m - 1, j))
return -1;
}
int res = 0;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
res += flip[i][j];
return res;
}
void solve()
{
int res = -1;
for (int i = 0; i < 1 << n; i++)
{
memset(flip, 0, sizeof(flip));
for (int j = 0; j < n; j++)
flip[0][n - 1 - j] = i >> j & 1;
int num = cal();
if (num >= 0 && (res < 0 || res > num))
{
res = num;
memcpy(opt, flip, sizeof(flip));
}
}
if (res < 0)
puts("IMPOSSIBLE");
else
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
printf("%d%c", opt[i][j], j == n - 1 ? '\n' : ' ');
}
}
}
int main()
{
while (cin >> m >> n)
{
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
cin >> tile[i][j];
solve();
}
return 0;
}
相关文章推荐
- Fliptile POJ - 3279 (状态压缩+枚举) && Flip Game POJ - 1753(状态压缩+bfs暴力)
- POJ_3279_Fliptile_搜索、二进制枚举
- POJ - 3279----Fliptile(枚举,遍历)
- POJ 3279 Fliptile(状态压缩+暴力)
- POJ 3279 Fliptile(二进制枚举暴力)
- POJ -3279 Fliptile (二进制转换,枚举每行)
- POJ 3279 Fliptile(反转+二进制枚举)
- 【POJ 3279 Fliptile】开关问题,模拟
- POJ - 3279 Fliptile(开关问题)
- POJ 3279 Fliptile——开关问题
- POJ 3279 Fliptile(DFS,想法)
- poj 3279 Fliptile(关灯问题)
- POJ 3279 Fliptile(状压搜索)
- poj3279 Fliptile【二进制枚举状态】
- 状态压缩+枚举 POJ 3279 Fliptile
- poj 3279--Fliptile(二维反转)
- POJ 3279 Fliptile(普通搜索)
- [kuangbin带你飞]专题一 简单搜索D - Fliptile(POJ 3279)
- Fliptile POJ 3279(开关问题)
- POJ 3279 Fliptile(开关问题)