pku_oj: 1681Painter's Problem(画家问题)(C++)
问题描述:
有一个正方形的墙,由N*N个正方形的砖组成,其中一些砖是白色的,另外一些砖是黄色的。Bob是个画家,想把全部的砖都涂成黄色。但他的画笔不好使。当他用画笔涂画第(i, j)个位置的砖时, 位置(i-1, j)、 (i+1, j)、 (i, j-1)、 (i, j+1)上的砖都会改变颜色。请你帮助Bob计算出最少需要涂画多少块砖,才能使所有砖的颜色都变成黄色。
输入:
第一行是一个整数n (1≤n ≤15),表示墙的大小。接下来的n行表示墙的初始状态。每一行包含n个字符。第i行的第j个字符表示位于位置(i,j)上的砖的颜色。“w”表示白砖,“y”表示黄砖。
输出:
一行,如果Bob能够将所有的砖都涂成黄色,则输出最少需要涂画的砖数,否则输出“inf”。
示例:
样例输入:
5 wwwww wwwww wwwww wwwww wwwww
样例输出:
15
代码(C++):
1 #include <iostream> 2 #include <math.h> 3 using namespace std; 4 int N, cnt; 5 int Brick[17][17]; 6 int Brick_copy[17][17]; 7 int Painting[17][17]; 8 9 void Breakdown(int); 10 int Execute(); 11 void Operating(int, int); 12 13 int main() 14 { 15 char a; 16 cin >> N; 17 for (int i = 1; i < N-1; ++i) 18 for (int j = 1; j < N-1; ++j) { 19 cin >> a; 20 Brick[i][j] = (a == 'w' ? 0 : 1); 21 } 22 int size = sizeof(Brick); 23 memcpy(Brick_copy, Brick, size); 24 int min = 99999; 25 for (int i = 0; i < pow(2, N); ++i) { 26 if (i > 0) 27 memcpy(Brick, Brick_copy, size); 28 Breakdown(i); 29 int n = Execute(); 30 if (n < min) 31 min = n; 32 } 33 if (min == 99999) 34 cout << "inf" << endl; 35 else 36 cout << min << endl; 37 } 38 39 void Breakdown(int x) 40 { 41 cnt = 0; 42 int j = N; 43 while (x > 0) { 44 Painting[1][j] = x & 1; 45 Operating(1, j); 46 j--; 47 x >>= 1; 48 } 49 } 50 51 int Execute() 52 { 53 for (int i = 2; i <= N; ++i) 54 for (int j = 1; j <= N; ++j) { 55 if (!Brick[i - 1][j]) { 56 Painting[i][j] = 1; 57 } 58 else { 59 Painting[i][j] = 0; 60 } 61 Operating(i, j); 62 } 63 64 for (int j = 1; j <= N; ++j) { 65 if (Brick[N][j] == 0) 66 return 99999; 67 } 68 return cnt; 69 } 70 71 void Operating(int i, int j) 72 { 73 if (Painting[i][j] == 1) { 74 Brick[i][j] ^= 1; 75 Brick[i - 1][j] ^= 1; 76 Brick[i][j - 1] ^= 1; 77 Brick[i][j + 1] ^= 1; 78 Brick[i + 1][j] ^= 1; 79 cnt++; 80 } 81 }