UVa 11214 Guarding the Chessboard

Problem G

Guarding the Chessboard

Given an n*m chessboard with some marked squares, your task is to place as few queens as possible to guard (attack or occupy) all marked squares. Below is a solution to an 8*8 board with every square marked. Note that queens can be placed on non-marked squares.

Input

The input consists of at most 15 test cases. Each case begins with a line containing two integers  n m  (1 <  n m  < 10), the size of the chessboard. Next  n  lines each contain  m  characters, 'X' denotes marked square, '.' denotes unmarked squares. The last case is followed by a single zero, which should not be processed.

Output

For each test case, print the case number and the minimal number of queens needed.

Sample Input

8 8
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
8 8
X.......
.X......
..X.....
...X....
....X...
.....X..
......X.
.......X
0

Output for the Sample Input

Case 1: 5
Case 2: 1

Rujia Liu's Present 2: A Big Contest of Brute Force


#include <cstdio>
#include <cstring>
// 现在的棋盘局势
char chess[10][10];

int row, col;

// 皇后个数
int max_d = 0;

// X在棋盘上的个数
int x_count = 0;


// t_col/dia1/dia2[i] = 1 代表该列/对角线已有皇后占用 
int t_row[10];
int t_col[10];
// 对角线:row-col
int t_dia1[20];
int base = 9;
// 对角线:row+col
int t_dia2[20];

bool dfs_search(int x, int this_row, int this_col);
//bool dfs_search(int x, int this_row);



int main()
{
	int g_count = 1;
	while(scanf("%d", &row) && row != 0)
	{
		scanf("%d", &col);
//		printf("row: %d col: %d\n", row, col);
		memset(chess, 0, sizeof(chess));
		x_count = 0;	
		for(int i = 0; i < row; i++)
		{
			scanf("%s", chess[i]);
			for(int j = 0; j < col; j++)
			{
				if(chess[i][j] == 'X')
					x_count++;
			}
		}
/*
		for(int i = 0; i < row; i++)
		{
			for(int j = 0; j < col; j++)
				printf("%c", chess[i][j]);
			printf("\n");
		}				
*/
		//迭代加深搜索
		for(max_d = 0; ; max_d++)		
		{
//			printf("max_d: %d\n", max_d);
			memset(t_row, 0, sizeof(t_row));
			memset(t_col, 0, sizeof(t_col));
			memset(t_dia1, 0, sizeof(t_dia1));
			memset(t_dia2, 0, sizeof(t_dia2));	
			if(dfs_search(1, 0, 0))
//			if(dfs_search(1, 0))
			{
				printf("Case %d: %d\n", g_count, max_d);
				break;
			}
		}
		g_count++;
	}		
	return 0;	
}


// 代表第i个皇后的行数和列数
int place_row[10];
int place_col[10];
// visit[i][j] = 1代表(i,j)被皇后占用
int visit[10][10];


// 迭代加深搜索
// 代表从this_row, this_col位置开始尝试放置第x个皇后
bool dfs_search(int x, int this_row, int this_col)
//bool dfs_search(int x, int this_row)
{
	// 搜索结束,检查是否满足条件
	if(x == max_d+1)
	{
		/*	
		for(int i = 0; i < row; i++)
		{
			for(int j = 0; j < col; j++)
			{
				if(chess[i][j] == 'X' && t_row[i] == 0 && t_col[j] == 0
					&& t_dia1[i-j+base] == 0 && t_dia2[i+j] == 0)
					return false;
			}
		}
		return true;
*/
		int rest_count = x_count;
		memset(visit, 0, sizeof(visit));
		// 依次检查每个皇后占用的情况
		for(int i = 0; i < max_d; i++)
		{
			int t_row = place_row[i];
			int t_col = place_col[i];
	
			// 检查该行
			for(int j = 0; j < col; j++)
			{
				if(chess[t_row][j] == 'X' && visit[t_row][j] == 0)
				{
					visit[t_row][j] = 1;
					rest_count--;
				}
			}		
			// 检查该列
			for(int j = 0; j < row; j++)
			{
				if(chess[j][t_col] == 'X' && visit[j][t_col] == 0)
				{
					visit[j][t_col] = 1;
					rest_count--;
				}
			}

			// 检查对角线1
			int j = 1;
			while(t_row-j >= 0 && t_col-j >= 0)
			{
				if(chess[t_row-j][t_col-j] == 'X' && visit[t_row-j][t_col-j] == 0)
                                {
                                        visit[t_row-j][t_col-j] = 1;
                                        rest_count--;
                                }
				j++;
			}	
			j = 1;
                        while(t_row+j < row && t_col+j < col)
                        {
                                if(chess[t_row+j][t_col+j] == 'X' && visit[t_row+j][t_col+j] == 0)
                                {
                                        visit[t_row+j][t_col+j] = 1;
                                        rest_count--;
                                }
                                j++;
                        }				

			// 检查对角线2
			j = 1;
			while(t_row-j >= 0 && t_col+j < col)
                        {
                                if(chess[t_row-j][t_col+j] == 'X' && visit[t_row-j][t_col+j] == 0)
                                {
                                        visit[t_row-j][t_col+j] = 1;
                                        rest_count--;
                                }
                                j++;
                        }
			j = 1;
                        while(t_row+j < row && t_col-j >= 0)
                        {
                                if(chess[t_row+j][t_col-j] == 'X' && visit[t_row+j][t_col-j] == 0)
                                {
                                        visit[t_row+j][t_col-j] = 1;
                                        rest_count--;
                                }
                                j++;
                        }
		}
		// 如果把位置占尽,返回true,否则返回false.	 
		if(rest_count == 0)
			return true;
		else
			return false;
	}

	// 尝试在各个可能的行摆放皇后
//	int end_row = row-1-(max_d-x);
	int end_row = row-1;
	for(int i = this_row; i <= end_row; i++)
	{
		int j;
		if(i == this_row)
			j = this_col;
		else
			j = 0;	
		// 确定可行的列
		for(; j < col; j++)
		{
/*			if(t_col[j] == 0 && t_dia1[i-j+base] == 0 && t_dia2[i+j] == 0)
			{
				t_col[j] = 1;
				t_dia1[i-j+base] = 1;
				t_dia2[i+j] = 1;
				place_row[x-1] = i;
				place_col[x-1] = j;	
				// 摆放下一个皇后
				if(dfs_search(x+1, i+1))
					return true;

				dfs_search(x+1, i+1);
				t_col[j] = 0;
                                t_dia1[i-j+base] = 0;
                                t_dia2[i+j] = 0;	
			}
*/		
			int x0 = t_row[i];
			int x1 = t_col[j];
			int x2 = t_dia1[i-j+base];
			int x3 = t_dia2[i+j];
			t_row[i] = 1;
			t_col[j] = 1;
			t_dia1[i-j+base] = 1;
			t_dia2[i+j] = 1;

			place_row[x-1] = i;
                    	place_col[x-1] = j;
			// 摆放下一个皇后
			int next_row, next_col;
			if(j == col-1)
			{
				next_row = i+1;
				next_col = 0;
			}
			else
			{
				next_row = i;
				next_col = j+1;
			}
                     	if(dfs_search(x+1, next_row, next_col))
                           	return true;
			t_row[i] = x0;
			t_col[j] = x1;
                     	t_dia1[i-j+base] = x2;
                      	t_dia2[i+j] = x3;
		}	
	}
	return false;	
}

迭代加深搜索。一开始想得是所有的皇后必须在不同行,不同列,不同对角线。

后来发现貌似这一条件并不成立,可以有皇后在相同行或相同列或相同对角线,但没有找到反例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值