题目大意:给定一个4*4矩阵,要么为白色要么为黑色,求按规则将其翻转为同一颜色的最少翻转次数(这里包括全为白色或者全为黑色)
分析:此题与POJ3279基本没啥区别,分析详见POJ3279解析:点击打开链接
附上代码:
#include<iostream>
using namespace std;
#define min(A,B) A<B?A:B
#define INF 0x3f3f3f3f
int a[6][6];
int b[6][6];
int d[5][2] = { { -1, 0 }, { 1, 0 }, { 0, 0 }, { 0, -1 }, { 0, 1 } };
int ans = INF;
bool getcolor(int x, int y) //返回x,y的颜色值
{
int res = a[x][y];
for (int i = 0; i < 5; i++)
{
int fx = x + d[i][0], fy = y + d[i][1];
if (fx >= 1 && fx <= 4 && fy >= 1 && fy <= 4) res += b[fx][fy];
}
return res % 2;
}
int solve()
{
int res = 0;
for (int i = 2; i <= 4; i++) //从第二行开始枚举是否需要翻转
for (int j = 1; j <= 4; j++)
if (getcolor(i - 1, j)) b[i][j] = 1;
for (int i = 1; i <= 4; i++) //判断最后一行是否满足条件
if (getcolor(4, i)) return INF;
for (int i = 1; i <= 4; i++) //求总翻转次数
for (int j = 1; j <= 4; j++)
res += b[i][j];
return res;
}
int main()
{
for (int i = 1; i <= 4; i++)
for (int j = 1; j <= 4; j++)
{
char ch;
cin >> ch;
if (ch == 'w') a[i][j] = 0;
else a[i][j] = 1;
}
for (int i = 2; i--;)
{
if (!i) //全翻转为白色或者全翻转为黑色都需枚举一次
{
for (int i = 1; i <= 4; i++)
for (int j = 1; j <= 4; j++)
a[i][j] = (a[i][j] + 1) % 2;
}
for (int s = 0; s < 1 << 4; s++) //枚举第一行有哪些翻转的情况
{
memset(b, false, sizeof b);
for (int i = 1; i <= 4; i++)
b[1][i] = s >> (4 - i) & 1;
int t = solve();
ans = min(ans, t);
}
}
if (ans == INF) printf("Impossible\n");
else printf("%d\n", ans);
return 0;
}