题目考虑到回溯,深度搜索
题目解读
Your task is to write a program that, given a description of a map, calculates the maximum number of blockhouses that can be placed in the city in a legal configuration.
目标是找到最合适的摆放位置
A bullet can run across any distance and destroy a blockhouse on its way. On the other hand, a wall is so strongly built that can stop the bullets.
The goal is to place as many blockhouses in a city as possible so that no two can destroy each other.
子弹可以像四个方向打出
墙可以阻挡子弹的飞射
要求是摆放的位置使得子弹不会打到放置建筑的位置
如图:
从这次的解题中可以学到
表示一个二维数组除了可以定义一个二维数组循环输入数以外,
还可以通过求余和做商在编程中的特点将其进行分组,
x = k / n;//横向坐标每n个是相同的
y = k % n;//纵向坐标每n个为一组
比如说题目中的 x 轴采用做商的方法,利用做商保留整数位的特点以分母的n作为基数,每n个为一组。
y轴利用求余取余数的特点,同样将y进行每n个为一组的分组,但不同的是,每组中的n个数都互不一样,且有规律的递增。
AC代码
#include<stdio.h>
int n;
char map[4][4];//题目要求最大4*4
int bestn;//标识符,标记放过炮塔的位置
int canput(int x, int y)
{
int i;
for (i = x - 1;i >= 0;i--)
{
if (map[i][y] == 'X')
{
break;
}
if (map[i][y] == 'o')
{
return 0;
}
}
for (i = y - 1;i >= 0;i--)
{
if (map[x][i] == 'X')
{
break;//wall直接退出判断
}
if (map[x][i] == 'o')
{
return 0;//为假结束判断
}
}
return 1;//为真结束判断
}
//K表示放置炮塔的位置
void backtrack(int k, int current)
{
int x, y;
if (k >= n * n)//k设置在1--n*n之间
{
if (current > bestn)
{
bestn = current;//赋予最大值
}
return;
}
else
{
x = k / n;//横向坐标每n个是相同的
y = k % n;//纵向坐标每n个为一组
if (map[x][y] == '.' && canput(x, y))//如果return 1 则继续执行if语句
{
map[x][y] = 'o';
backtrack(k + 1, current + 1);//执行顺序为(0,1)(0,2)....
map[x][y] = '.';
}
backtrack(k + 1, current);
}
}
int main()
{
while (scanf("%d", &n) != EOF)
{
int i, j;
bestn = 0;
for (i = 0;i < n;i++)
{
for (j = 0;j < n;j++)
{
char ch;
ch = getchar();
if (ch == '\n')
{
j--;
continue;
}
else
{
map[i][j] = ch;
}
}
}
backtrack(0, 0);
printf("%d\n", bestn);
scanf("%d", &n);
}
return 0;
}