百练/ 北京大学2016研究生推免上机考试(校外)F: Painter's Problem(枚举)

题目来源:http://poj.org/problem?id=1681

Painter's Problem

Time Limit: 1000MS

Memory Limit: 10000K

Total Submissions: 7436

Accepted: 3528

Description

There is a square wall which is made of n*nsmall square bricks. Some bricks are white while some bricks are yellow. Bob isa painter and he wants to paint all the bricks yellow. But there is somethingwrong with Bob's brush. Once he uses this brush to paint brick (i, j), thebricks at (i, j), (i-1, j), (i+1, j), (i, j-1) and (i, j+1) all change theircolor. Your task is to find the minimum number of bricks Bob should paint inorder to make all the bricks yellow. 


Input

The first line contains a single integer t (1<= t <= 20) that indicates the number of test cases. Then follow the tcases. 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 originalwall. Each line contains n characters. The j-th character of the i-th linefigures out the color of brick at position (i, j). We use a 'w' to express awhite brick while a 'y' to express a yellow brick.

Output

For each case, output a line contains theminimum number of bricks Bob should paint. If Bob can't paint all the bricksyellow, print 'inf'.

Sample Input

2

3

yyy

yyy

yyy

5

wwwww

wwwww

wwwww

wwwww

wwwww

Sample Output

0

15

-----------------------------------------------------

解题思路

枚举,注意到第一行n个节点的2^n种涂色方法就是所有的涂色方法,因为之后每次涂色都是把上一行的白色格子变成黄色格子,是唯一确定的,否则变来变去肯定涂色次数更大。

-----------------------------------------------------

代码

 

//F:画家问题
//总时间限制: 1000ms 内存限制: 65536kB
//描述
//有一个正方形的墙,由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<fstream>
#include<iostream>
#include<limits.h>
#include<cstring>
using namespace std;

const int MAX = 15;

bool map[MAX][MAX];						// 1: y; 0: w
bool map_copy[MAX][MAX];					// map的副本: 每次涂色会改变map,所以要用副本
static int cnt = 0;						// 画的次数

void draw(int x, int y, int n)			// 画一笔,周围的都变色
{
	map_copy[x][y] = !map_copy[x][y];
	if (x>0)
	{
		map_copy[x-1][y] = !map_copy[x-1][y];
	}
	if (y>0)
	{
		map_copy[x][y-1] = !map_copy[x][y-1];
	}
	if (x<n-1)
	{
		map_copy[x+1][y] = !map_copy[x+1][y];
	}
	if (y<n-1)
	{
		map_copy[x][y+1] = !map_copy[x][y+1];
	}
	cnt++;
}

int draw_first(int n)	// 枚举第一行所有2^n种的画的情况,之后根据第一行的情况画,只有w的地方才画
{
	int num = (2 << n) - 1,i,j,it,mincnt = INT_MAX;
	// 枚举所有2^n种情况画第一行,一共就这2^n种涂色方法
	for (it=0; it<=num; it++)
	{
		memcpy(map_copy, map, sizeof(map));
		cnt = 0;
		for (i=0; i<n; i++)
		{
			if ((it >> i)%2)
			{
				draw(0,i,n);
			}
		}
		// 从第二行开始根据第一行涂完的结果涂
		for (i=1; i<n; i++)
		{
			for (j=0; j<n; j++)
			{
				if (!map_copy[i-1][j])	// 如果上一行该节点是白的
				{
					draw(i,j,n);		// 将这行的对应点涂黄
				}
			}
		}
		// check最后一行是否都涂成黄色了
		for (i=0; i<n; i++)
		{
			if (!map_copy[n-1][i])		// 如果最后一行还有格子没涂
			{
				cnt = INT_MAX;			// 则该种涂色方式不可行
				break;
			}
		}
		if (cnt < mincnt)
		{
			mincnt = cnt;				// 找最小的涂色次数
		}
	}
	return mincnt;
}



int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin("tm201602F.txt");
	int t,n,i,j,ii,ans=0;
	char tmp;
	fin >> t;
	for (ii=0; ii<t; ii++)
	{
		cnt = 0;
		fin >> n;
		for (i=0; i<n; i++)
		{
			for (j=0; j<n; j++)
			{
				fin >> tmp;
				if (tmp == 'y')
				{
					map[i][j] = true;
				}
				else
				{
					map[i][j] = false;
				}
			}
		}
		if (n==1 && map[0][0] == true)
		{
			cout << 0 << endl;
		}
		else if (n==1 && map[0][0] == false)
		{
			cout << 1 << endl;
		}
		else
		{
			ans = draw_first(n);
			if (ans < INT_MAX)
			{
				cout << ans << endl;
			}
			else
			{
				cout << "inf" << endl;
			}
		}
	}
	fin.close();
#endif
#ifdef ONLINE_JUDGE
	int t,n,i,j,ii,ans=0;
	char tmp;
	cin >> t;
	for (ii=0; ii<t; ii++)
	{
		cnt = 0;
		cin >> n;
		for (i=0; i<n; i++)
		{
			for (j=0; j<n; j++)
			{
				cin >> tmp;
				if (tmp == 'y')
				{
					map[i][j] = true;
				}
				else
				{
					map[i][j] = false;
				}
			}
		}
		if (n==1 && map[0][0] == true)
		{
			cout << 0 << endl;
		}
		else if (n==1 && map[0][0] == false)
		{
			cout << 1 << endl;
		}
		else
		{
			ans = draw_first(n);
			if (ans < INT_MAX)
			{
				cout << ans << endl;
			}
			else
			{
				cout << "inf" << endl;
			}
		}
	}
#endif
}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/80306061