原题链接:1443. 拍照 - AcWing题库
解题思路:本题可以通过DFS来解决。首先题目要求字典序最小,也就是第一位尽可能小,所以从1开始尝试到n。之后的数都可以通过b数组对应位置减去a数组前一位的数字得到此位的编号。
因为是编号,所以不能有重复的和非正整数出现,一旦出现就直接返回搜索其他路径。而第一个合法填满的数组必定是字典序最小的,输出后直接结束整个DFS即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
long long a[11000],b[11000],n,bucket[11000];//前三个变量为题原意,bucket数组记录数是否有用过
int dfs(int c){
if(c==n){//合法到第n层说明0到n-1一共n个数已经填完了,直接输出
for(int i=0;i<n;i++) cout<<a[i]<<' ';
return 1;//返回值是1,如果检测到返回值是1会直接结束后面所有尝试
}
int buffer;//记录此时按照b[i]-a[i-1]得出来的数
buffer=b[c]-a[c-1];
if(bucket[buffer]||buffer<=0) return 0;//如果值用过,或者小于等于0说明编号不合法,返回,且返回值是0,会继续尝试
bucket[buffer]=1,a[c]=buffer;//记录
if(dfs(c+1)==1) return 1;
bucket[buffer]=0;//释放
return 0;
}
int main(){
cin>>n;
for(int i=1;i<n;i++) cin>>b[i];
for(int i=1;i<=n;i++){//因为字典序最小,所以第一位尽可能小
a[0]=i;
bucket[i]=1;//记录该数已被占用
if(dfs(1)) break;
bucket[i]=0;//释放该数
}
return 0;
}