画家问题

问题来源:

http://cxsjsxmooc.openjudge.cn/test/Y/

描述

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

 

解决代码:

#include<iostream>
#include<math.h>
#include<string>
using namespace std;

int t, n, pow2, num;
int **puzzle;//初始化的二维数组,用于标记墙壁最初时各砖块的颜色
int **press;//二维数组,用于标记墙壁的某个砖块是否需要进行上色

void initialization(int temp, char **tempArray) {
	n = temp;
	t = 0;
	pow2 = pow(2, n);
	puzzle = new int*[n + 1];//新创建出一个n+1行,n+2列的二维int数组以实现涂砖块的标记,初始化后的第0行和第0列以及n+1列均为1(即为黄色),此后用该二维数组实现局部枚举以推出整体的情况
	press = new int*[n + 1];
	for (int i = 0; i <= n; i++) {
		puzzle[i] = new int[n + 2];
		press[i] = new int[n + 2];
	}
	for (int i = 0; i < n + 2; i++) {
		puzzle[0][i] = 1;
		press[0][i] = 0;
	}
	for (int i = 1; i < n + 1; i++) {
		puzzle[i][0] = 1;
		puzzle[i][n + 1] = 1;
		press[i][0] = 0;
		press[i][n + 1] = 0;
		for (int j = 1; j < n + 1; j++) {
			if (tempArray[i-1][j-1] == 'y')
				puzzle[i][j] = 1;
			else if (tempArray[i - 1][j - 1] == 'w')
				puzzle[i][j] = 0;
		}
	}
}

int guess() {
	int c, r;
	num = 0;
	for (c = 1; c < n + 1; c++) {
		if (press[1][c] == 1)
			num++;
	}
	for (r = 1; r < n; r++)
		for (c = 1; c < n+1; c++) {
			press[r + 1][c] = (puzzle[r][c] + press[r][c] + press[r - 1][c] + press[r][c - 1] + press[r][c + 1] + 1) % 2;
			if (press[r + 1][c] == 1)
				num++;
		}
	for (c = 1; c < n+1; c++)
		if ((press[n][c - 1] + press[n][c] + press[n][c + 1] + press[n - 1][c] + 1) % 2 != puzzle[n][c])
			return(-1);
	return(num);
}

int enumerate() {//局部状态的枚举函数以推出整体状态的情况
	int c;
	for (c = 1; c < n+1; c++) {
		press[1][c] = 0;
	}
	press[1][1] = -1;
	int g = -1;
	do {
		press[1][1]++;
		c = 1;
		while (press[1][c] > 1) {
			press[1][c] = 0;
			c++;
			press[1][c]++;
		}
		g=guess();
		t++;
	} while (g == -1&&t<=pow2);
	if (t <= pow2) {
		return num;//当t<=pow2时,说明问题有解,此时返回num,即为问题的解(即刷砖块的次数)
	}
	else if (t > pow2) {
		num = -1;
		return num;//返回-1表示此问题无解
	}
	//该函数需要补全的部分:当函数运行2^n次后函数自动结束并输出inf,否则输出刷砖块的次数
}

int main()
{
	int round;
	cin>> round;
	for (int i = 0; i < round; i++) {
		int temp;
		cin>> temp;
		cin.get();
		char** temparr = new char*[temp];
		for (int j = 0; j < temp; j++) {
			temparr[j] = new char[temp+1];
		}
		for (int r = 0; r < temp; r++) {
			cin.getline(temparr[r],temp+1);
		}
		initialization(temp, temparr);
		enumerate();
		if (num == -1)
			cout << "inf" << endl;
		else
			cout << num << endl;
	}
	return 0;
}

 

P.S. 改代码可以成功通过POJ的测试,但是在Course上无法通过,若想在Course上通过需要对Main函数进行修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值