题意
给定
n
×
n
n\times n
n×n 的地图
从左上角走到右下角 四联通方向 每走到一个格子 向正北和正西射一支箭 每个点只能走一次
题目给出最后竖向和横向上的每个靶子上的箭的总数
题目保证路径唯一 求出行走路径
题目约定每个小格子用一个数字代表,从西北角开始编号:
0
,
1
,
2
,
3...
0,1,2,3 ...
0,1,2,3...
数据范围
0
<
=
N
<
=
20
0<=N<=20
0<=N<=20
思路
开col[N] row[N]数组记录当前每一行/列 上有多少只箭
设计
d
f
s
(
i
n
t
x
,
i
n
t
y
,
i
n
t
i
d
x
)
dfs(int \space x,int \space y,int \space idx)
dfs(int x,int y,int idx)
x,y 表示上一个点的坐标 这一次dfs要通过(x,y)的四个方向扩展
idx表示上一次是第几步 (从0开始) 用于path数组记录 填充和撤销
(我一开始没开idx这一维,回溯用pop_back 这样没法正确撤销选择)
dfs枚举所有方案 如果可行 就输出答案
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
#define ar2 array<int,2>
#define ar3 array<int,3>
#define ar4 array<int,4>
#define endl '\n'
void cmax(int &a,int b){a=max(a,b);}
void cmin(int &a,int b){a=min(a,b);}
const int N=100,MOD=1e9+7,INF=0x3f3f3f3f,LINF=LLONG_MAX;
int a[N],b[N],col[N],row[N],n;
bool vis[N][N];
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
vector<int>path(500,-1);
void dfs(int x,int y,int idx){
if(x==n-1&&y==n-1) {
for(int i=0;i<n;i++){
if(col[i]!=a[i]||row[i]!=b[i]){
return;
}
}
for(int i=0;i<=idx;i++) cout<<path[i]<<' ';cout<<endl;
return;
}
for(int i=0;i<4;i++){
int tx=x+dx[i],ty=y+dy[i];
if(tx<0||tx>=n||ty<0||ty>=n||vis[tx][ty]) continue;
if(col[ty]==a[ty]&&row[tx]==b[tx]){
continue;
}
col[ty]++,row[tx]++;
if(col[ty]>a[ty]||row[tx]>b[tx]){
col[ty]--,row[tx]--;
continue;
}
vis[tx][ty]=1;
path[idx+1]=tx*n+ty;
dfs(tx,ty,idx+1);
vis[tx][ty]=0;
path[idx+1]=-1;
col[ty]--,row[tx]--;
}
}
void solve() {
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
vis[0][0]=1;
path[0]=0;
col[0]++,row[0]++;
dfs(0,0,0);
// for(int i:path) cout<<i<<' ';cout<<endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t=1;
// cin>>t;
while (t--) solve();
}
细节
if(x==n-1&&y==n-1) {
for(int i=0;i<n;i++){
if(col[i]!=a[i]||row[i]!=b[i]){
return;
}
}
for(int i=0;i<=idx;i++) cout<<path[i]<<' ';cout<<endl;
return;
}
这段代码注意要在x==-1&&y==n-1 时return
因为x,y代表上一次走的点 既然上一次已经走到右下角了 就不要继续往下走了
另外 要判断每个行列的箭数目是否匹配 如果匹配才要输出path