POJ1681 Painter‘s Problem【暴力】

Painter’s Problem
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 8282 Accepted: 3874

Description

There is a square wall which is made of n*n small square bricks. Some bricks are white while some bricks are yellow. Bob is a painter and he wants to paint all the bricks yellow. But there is something wrong with Bob’s brush. Once he uses this brush to paint brick (i, j), the bricks at (i, j), (i-1, j), (i+1, j), (i, j-1) and (i, j+1) all change their color. Your task is to find the minimum number of bricks Bob should paint in order to make all the bricks yellow.
POJ1681 Painter‘s Problem【暴力】_第1张图片

Input

The first line contains a single integer t (1 <= t <= 20) that indicates the number of test cases. Then follow the t cases. Each test case begins with a line contains an integer n (1 <= n <= 15), representing the size of wall. The next n lines represent the original wall. Each line contains n characters. The j-th character of the i-th line figures out the color of brick at position (i, j). We use a ‘w’ to express a white brick while a ‘y’ to express a yellow brick.

Output

For each case, output a line contains the minimum number of bricks Bob should paint. If Bob can’t paint all the bricks yellow, print ‘inf’.

Sample Input

2
3
yyy
yyy
yyy
5
wwwww
wwwww
wwwww
wwwww
wwwww

Sample Output

0
15

Source

POJ Monthly–2004.06.27 张嘉龄

问题链接:POJ1681 Painter’s Problem
问题简述:(略)
问题分析:这个问题与参考链接可以说是同一个问题,只是输入输出不同。解题代码是使用那个代码修改而来,同样采用暴力法实现。

数据表示方面,使用数组press[][]来存储开关按下标记。需要扩充1行即下标为0的行,需要扩充2列即下标为0的列和下标为7的列。press[i][j]=1表示第i行第j列需要按下,press[i][j]=0表示第i行第j列不需要按下。
采用逐行枚举的方法来实现。对第一行进行枚举,枚举所有的可能(000000-111111),开始时先看第一行为000000(都不按按钮)的情况,然后采用逐步加1的方式来实现。
首先需要关掉第i行的灯,可以通过按第i+1行来实现。一般而言,若b[i][j]灯亮,则需要按b[i+1][j]。这样,可以采用从第2行开始,逐行递推进行暴力枚举方法来解决。
另外,press[i][j]值由初始灯的状态,和前面行按按钮的情况算出。
程序说明:(略)
参考链接:Bailian2813 画家问题【暴力】
题记:(略)

AC的C++语言程序如下:

/* POJ1681 Painter's Problem */

#include 
#include 
#include 

using namespace std;

const int N = 15;
char g[N + 1][N + 2];
int b[N + 1][N + 2], press[N + 1][N + 2];
int ans;

void solve(int n)
{
    for(int i = 2 ; i <= n; i++) {
        for(int j = 1 ; j <= n; j++) {
            press[i][j] = (b[i - 1][j] + press[i - 1][j] + press[i - 1][j - 1] + press[i - 2][j] + press[i - 1][j + 1]) % 2;

        }
    }

    /* 检查最后一行是否都已经关灯 */
    bool flag = true;
    for(int j = 1 , i = n + 1; j <= n ; j++) {
        int t = (b[i - 1][j] + press[i - 1][j] + press[i - 1][j - 1] + press[i - 2][j] + press[i - 1][j + 1]) % 2;
        if(t) {flag = false; break;}
    }

    if(flag) {
        int cnt = 0;
        for(int i = 1 ; i <= n; i++)
            for(int j = 1 ; j <= n; j++)
                if(press[i][j]) cnt++;
        ans = min(ans, cnt);
    }
}

int main()
{
    int t, n;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        getchar();
        for(int i = 1; i <= n; i++)
            scanf("%s", g[i] + 1);

        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                if(g[i][j] == 'w') b[i][j] = 1;
                else if(g[i][j] == 'y') b[i][j] = 0;


        memset(press, 0, sizeof(press));
        ans = n * n + 1;
        for(;;) {
            solve(n);

            /* 对于第1行进行枚举,000000-111111,采用加1方式实现 */
            int t = 1;
            press[1][t]++;
            while(press[1][t] > 1) {
                press[1][t] = 0;
                t++;
                press[1][t]++;
            }
            if(t > n) break;
        }

        if(ans == n * n + 1)
            printf("inf\n");
        else
            printf("%d\n", ans);
    }

    return 0;
}

你可能感兴趣的:(POJ1681 Painter‘s Problem【暴力】)