题目
题解
DFS。
半模板题,就多了个限制,这个限制可以作为剪枝条件剪掉,也可以作为限制条件防止走错误的步。
下面代码中的check函数和dfs中第二个continue的条件就是利用了题目中对箭数的要求。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
int n, vis[N], best[N], nor_arr[N], wes_arr[N], nor[N], wes[N];
bool check() { // 判断是否满足箭数要求
for(int i = 0;i < n;i ++)
if(nor_arr[i] != nor[i] || wes_arr[i] != wes[i]) return false;
return true;
}
void dfs(int pos, int cnt) { // 第一个参数为位置,第二个为步数
if(pos == n*n-1) { // 到达出口
if(check()) for(int i = 0;i <= cnt;i ++) cout << best[i] << ' '; // 若满足要求的箭数,则输出
return ;
}
int x = pos/n, y = pos%n;
for(int i = 0;i < 4;i ++) {
int tx = x+dx[i], ty = y+dy[i];
int cur = tx*n+ty;
if(vis[cur] || tx < 0 || ty < 0 || tx >= n || ty >= n) continue;
if(nor_arr[ty] == nor[ty] || wes_arr[tx] == wes[tx]) continue; // 如果还没走这步箭数就与要求相等了,则这步必然错了
nor_arr[ty] ++, wes_arr[tx] ++; // 箭数
vis[cur] = 1;
dfs(cur, cnt+1);
vis[cur] = 0;
nor_arr[ty] --, wes_arr[tx] --;
}
}
int main()
{
cin>>n;
for(int i = 0;i < n;i ++) cin >> nor[i]; // 北面箭的数量
for(int i = 0;i < n;i ++) cin >> wes[i]; // 南面箭的数量
nor_arr[0] = wes_arr[0] = 1; // 向北面和南面射出的箭的数量
vis[0] = 1;
best[0] = 0; // 答案数组
dfs(0, 0);
return 0;
}