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;
}
迭代加深搜索。一开始想得是所有的皇后必须在不同行,不同列,不同对角线。
后来发现貌似这一条件并不成立,可以有皇后在相同行或相同列或相同对角线,但没有找到反例。