枚举 画家问题

问题描述:

有一个正方形的墙,由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”。


算法分析:

和熄灯问题很相似,略有改动

#include <iostream>
using namespace std;


int wall[16][17]={0},press[16][17]={0};
//黄色为0,白色表示1
/*
推测验证过程:
根据第一行猜测
*/
int guess(const int& wallsize) {    
    //根据press第1行和wall数组,计算press其他行的值
    for (int r=1; r<wallsize; r++) {
        for (int c=1; c<=wallsize; c++) {
            press[r+1][c]=(wall[r][c]+press[r][c]+press[r-1][c]+press[r][c-1]+press[r][c+1])%2;
        }
    }
    //判断所计算的press数组能否将最后一行全变为黄色0
    for(int c=1; c<=wallsize; c++) {
        if ((press[wallsize][c-1]+press[wallsize][c]+press[wallsize][c+1]+press[wallsize-1][c])%2 != wall[wallsize][c]) {
            return 1001;            
        }
    }
    //算出需要的步数
    int steps=0;
    for (int r=1; r<=wallsize; r++) {
        for (int c=1; c<=wallsize; c++) {
            if (press[r][c]==1) {
                steps++;
            }
        }
    }
    return steps;
}
/*
枚举过程:
对press第1行的元素press[1][1]~press[1][6]的各种取值进行枚举
*/
int enumerate(const int& wallsize) {
    int minsteps=1001;
    int steps=0;
    int c;
    while (press[1][wallsize+1]<1){
        steps = guess(wallsize);
        if (steps<minsteps){
            minsteps = steps;
        }       
        press[1][1]++;
        c=1;
        while(press[1][c]>1) {
            press[1][c]=0;
            c++;
            press[1][c]++;
        }
    }
    return minsteps;
}


int main() {
    int cases=0;
    cin >> cases;
    char color;
    int wall_size=0;
    int minsteps=0;
    for(int k=0; k<cases; k++) {    
        //初始化
        for (int r=0; r<16; r++){
            for (int c=0; c<17; c++){
                wall[r][c]=0;
                press[r][c]=0;
            }
        }
        //输入数据
        cin >> wall_size;
        for(int i=1; i<wall_size+1; i++) {
            for (int j=1; j<wall_size+1; j++){              
                cin >> color;
                wall[i][j] = color=='y' ? 0:1;
            }
        }
        //枚举
        minsteps = enumerate(wall_size);
        if (minsteps>1000){
            cout << "inf" << endl;
        }
        else {
            cout << minsteps << endl;
        }
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值