枚舉 編程題#1: 畫家問題(Coursera 程序設計與算法 專項課程4;枚舉方法:用二進制依次加1的進位方法模擬實現)

編程題#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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章