自己首先写了一个dfs,只能过一个测试点,后来发现我是按照所给样例的大小来开数组的,把数组开到符合题目要求后,第二个测试点也通过了,但是剩下了测试点依旧很多都超时,于是加上了两个剪枝操作,能够100%通过所有测试点。
#include <bits/stdc++.h>
using namespace std;
int n;
int path[25][25], vis[25][25];
int north[25], west[25];
int north_tru[25], west_tru[25];
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
vector<int> vv;
bool flag = false;
bool judge() {
for (int i = 1; i <= n; i++) {
if (north[i] != north_tru[i] || west[i] != west_tru[i])
return false;
}
return true;
}
void dfs(int x, int y) {
if (flag) return ; // 剪枝,找到答案后就提前结束,不要再去遍历所有情况了
// 因为题目保证了路径唯一
if (x == n && y == n) {
if (judge()) {
// 输出路径
for (int i = 0; i < vv.size(); i++) {
cout << vv[i] << " ";
}
flag = true;
}
return ;
}
for (int i = 0; i < 4; i++) {
int tx = x + dx[i];
int ty = y + dy[i];
if (tx <= 0 || tx > n || ty <= 0 || ty > n) continue;
if (!vis[tx][ty]) {
if (west[tx] >= west_tru[tx] || north[ty] >= north_tru[ty]) continue; // 最关键的一个剪枝,不加上的话,会超时
vis[tx][ty] = 1;
west[tx]++, north[ty]++; // 向正北方和正西方各射一箭
vv.push_back(path[tx][ty]); // 记录路径
dfs(tx, ty);
vis[tx][ty] = 0;
west[tx]--, north[ty]--;
vv.pop_back();
}
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> north_tru[i];
}
for (int i = 1; i <= n; i++) {
cin >> west_tru[i];
}
int k = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
path[i][j] = k;
k++;
}
}
vis[1][1] = 1;
west[1]++, north[1]++;
vv.push_back(path[1][1]);
dfs(1,1);
return 0;
}