編程題#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.csdn.net/qq_30258957/article/details/54884977