编程题#1: 画家问题
来源: POJ (http://bailian.openjudge.cn/practice/2813/)
注意: 总时间限制: 1000ms 内存限制: 65536kB
描述
有一个正方形的墙,由N*N个正方形的砖组成,其中一些砖是白色的,另外一些砖是黄色的。Bob是个画家,想把全部的砖都涂成黄色。但他的画笔不好使。当他用画笔涂画第(i, j)个位置的砖时, 位置(i-1, j)、 (i+1, j)、 (i, j-1)、 (i, j+1)上的砖都会改变颜色。请你帮助Bob计算出最少需要涂画多少块砖,才能使所有砖的颜色都变成黄色。
输入
第一行是个整数t(1≤t ≤20),表示要测试的案例数。然后是t个案例。每个案例的首行是一个整数n (1≤n ≤15),表示墙的大小。接下来的n行表示墙的初始状态。每一行包含n个字符。第i行的第j个字符表示位于位置(i,j)上的砖的颜色。“w”表示白砖,“y”表示黄砖。
输出
每个案例输出一行。如果Bob能够将所有的砖都涂成黄色,则输出最少需要涂画的砖数,否则输出“inf”。
样例输入
2
3
yyy
yyy
yyy
5
wwwww
wwwww
wwwww
wwwww
wwwww
样例输出
0
15
程序解答:
#include <iostream>
using namespace std;
int getPaintNum(int paint[][17]){ //获得每次成功的喷涂数
int num = 0;
for (int i = 0; i < 16; i++){
for (int j = 0; j < 17; j++)
num += paint[i][j];
}
return num;
}
bool guessNum(int wall[][17], int paint[][17], int n){ //判断喷涂是否成功
int c, r;
//根据画板颜色和周围paint颜色值判断下一行paint的颜色值
for (r = 1; r<n; r++)
for (c = 1; c <= n; c++)
paint[r + 1][c] = (wall[r][c] + paint[r][c] + paint[r - 1][c] + paint[r][c - 1] + paint[r][c + 1]) % 2;
//判断最后一行能否被画成黄色
for (c = 1; c <= n; c++)
if ((paint[n][c - 1] + paint[n][c] + paint[n][c + 1] + paint[n-1][c]) % 2 != wall[n][c])
return(false);
return(true);
}
void theLeastPaints(int wall[][17], int paint[][17], int n){ //输出最少喷涂数
int leastNum = 16 * 17; //最少喷涂砖块数
int c, cTemp = 0;
while (1){
if (guessNum(wall, paint, n) == true){
if (leastNum > getPaintNum(paint))
leastNum = getPaintNum(paint);
}
//枚举第一行的所有情况,枚举方法:用二进制依次加1的进位方法模拟实现
paint[1][1]++;
c = 1;
while (paint[1][c] > 1) {
paint[1][c] = 0;
c++;
if (c > cTemp)
cTemp = c;
paint[1][c]++;
}
if (cTemp > n)
break;
}
if (leastNum == 16 * 17)
cout << "inf" << endl;
else
cout << leastNum;
}
int main(){
int wall[16][17]; //墙的颜色矩阵,行数15+1,列数15+2;1表示白色,0表示黄色,都先置0
int paint[16][17]; //涂画矩阵,行数15+1,列数15+2;0表示不涂画,1表示涂画,都先置0
int t;
int n; //墙的大小
char c; //墙的颜色
cin >> t;
while (t--){
//矩阵初始化为 0,要专门初始化!!!
for (int i = 0; i < 16; i++){
for (int j = 0; j < 17; j++){
wall[i][j] = 0;
paint[i][j] = 0;
}
}
cin >> n;
for (int i = 1; i < n+1; i++){
for (int j = 1; j < n+1; j++){
cin >> c;
if (c == 'w')
wall[i][j] = 1;
}
}
theLeastPaints(wall, paint, n);
}
return 0;
}
附:
听课思路总结参考
枚举的应用:熄灯问题&讨厌的青蛙:http://blog.youkuaiyun.com/qq_30258957/article/details/54884977