hrbust 1042 过河卒[ dfs ]
题目链接 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; }