题目链接 http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1042
思路:卒子所在行枚举答案,然后dfs求解。
/*
* hrbust1042过河卒
* 思路:卒子所在行枚举答案,然后进行不重复深搜。
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char res[10]; //记录卒子所在行的状态,用来枚举当前行。
char map[6][10]; //存放棋盘。
int sum, k, tot, pd; //每次深搜的结果,要走的步数,卒子所在行到第0行对方棋子的总数,用来判断是否可以吃掉对方全部棋子。
int dir[3][2] =
{
{0, 1}, {0, -1}, {-1, 0}
};
//深搜,参数:行,列,走的步数,吃掉棋子的个数。
void dfs(int x, int y, int step, int ans)
{
int bl = 0;//判断是否搜索到对方棋子了,如果搜到了,那么bl = 1,用来当前搜索结束后更新这个棋子。
if(map[x][y] == 'K') {
ans++; //如果搜到了,则ans加1.
//如果走的步数等于给出的步数,搜索结束。
if(step == k) {
sum = max(sum, ans); //更新sum
if(sum == tot ) pd = 2; //如果搜到的总数等于卒子所在行到第0行对方棋子的总数,那么答案就可以确定了,没必要继续下去。
return ;
}
bl = 1;
}
if(step == k) {
sum = max(sum, ans);
if(sum == tot ) pd = 2;
return ;
}
if(pd == 2) return ;
map[x][y] = 'X'; //进行不重复深搜,所以要把访问过的位置标记一下,之后在还原。
//向题中所给出的3个方向进行搜索。
for(int i = 0; i < 3; i++) {
int a = x + dir[i][0];
int b = y + dir[i][1];
if(a >= 0 && a < 5 && b >= 0 && b < 9 && map[a][b] != 'X') {
dfs(a, b, step+1, ans);
}
}
map[x][y] = '*';
if( bl ) map[x][y] = 'K';
}
int main()
{
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &k);
int x = 10, y; //初始化x用来统计tot的个数。
tot = 0;
for(int i = 0; i < 5; i++) {
scanf("%s", map[i]);
for(int j = 0; j < 9; j++) {
if(map[i][j] == 'L') {
x = i;
y = j;
}
if(map[i][j] == 'K' && x >= i) tot++;
}
}
//如果k太大,就需要进行剪枝,k等于k和卒子当前位置到最后一行要走的最多的步数中较小的一个。
k = min(((x+1)*9-1) + (8-y > y ? y : 8-y), k);
//如果tot等于0,那么答案很明显,没必要继续下去了.
if(tot == 0) {
printf("0\n");
continue;
}
int a = 0; //a用来记录枚举时候的对方棋子的个数。
int tmp = tot; //记录tot的值,等会还原tot会用到。
int tmp2 = k; //记录k的值。
strcpy(res, map[x]); //记录卒子所在行的状态。
int da_an = 0; //最后的答案。
//开始枚举当前行。先向左枚举.
for(int i = y; i >= 0; i--) {
sum = 0;
pd = 0;
a = 0;
tot = tmp;
k = tmp2;
//改变当前行状态,因为我们在枚举的时候已经知道了a,所以深搜的时候不能再有对方棋子出现。
for(int j = i; j <= y; j++) {
if(map[x][j] == 'K') {
a++;
map[x][j] = '*';
}
}
//改变步数。
k -= (y-i);
if(k <= 0) break;
//改变tot.
tot -= a;
dfs(x, i, 0, 0); //开始搜索。
sum += a;
da_an = max(da_an, sum); //更新答案。
//还原卒子所在行状态,以便下次枚举。
for(int j = 0; j < 9; j++) {
map[x][j] = res[j];
}
}
//向右枚举,和上面操作基本类似。
for(int i = y; i < 9; i++) {
sum = 0;
pd = 0;
a = 0;
tot = tmp;
k = tmp2;
for(int j = y; j <= i; j++) {
if(map[x][j] == 'K') {
a++;
map[x][j] = '*';
}
}
k -= (i-y);
if(k <= 0) break;
tot -= a;
dfs(x, i, 0, 0);
sum += a;
da_an = max(da_an, sum);
for(int j = 0; j < 9; j++) {
map[x][j] = res[j];
}
}
printf("%d\n", da_an);
}
return 0;
}