weight (搜索对象的选取)

#10249. 「一本通 1.3 例 5」weight

【题目描述】

已知原数列 $a_1,a_2,cdots,a_n$​​ 中的前 1项,前 2 项,前3项, $cdots$ ,前 n 项的和,以及后 1 项,后 2 项,后 3 项, $cdots$ ,后 n 项的和,但是所有的数都被打乱了顺序。此外,我们还知道数列中的数存在于集合 S 中。试求原数列。当存在多组可能的数列时,求字典序最小的数列。

【算法】

将前后缀和排序,依次判断是当前第一个前缀还是当前第一个后缀,同时只需搜索出前后缀共n-1个即可求出序列,同时根据前缀和的单调性显然这n-1个必然是a数组的前n-1个数,同时对每一个$a_i$显然有$all-a_i$与之匹配,所以只要确定好n个,则前后缀序列必定能构建出来。

【代码】

#include <bits/stdc++.h>
using namespace std;
int n,m,x,all;
int a[2010],v[2010],ans[1010],rec[510];
inline int read() {
    int x=0,f=1; char c=getchar();
    while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
    while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); }
    return x*f;
}
bool dfs(int l,int r,int now,int pre,int post) {
    int x;
    if(l==r) {
        x=all-pre-post;
        if(x>=1&&x<=500&&rec[x]) {
            ans[l]=x;
            return 1;
        }
        return 0;
    }
    x=a[now]-pre;
    if(x>=1&&x<=500&&rec[x]) {
        ans[l]=x;
        if(dfs(l+1,r,now+1,a[now],post)) return 1;
    }
    x=a[now]-post;
    if(x>=1&&x<=500&&rec[x]) {
        ans[r]=x;
        if(dfs(l,r-1,now+1,pre,a[now])) return 1;
    }
    return 0;
}
int main() {
    n=read();
    for(int i=1;i<=2*n;i++) a[i]=read();
    m=read();
    for(int i=1;i<=m;i++) x=read(),rec[x]=1;
    sort(a+1,a+2*n+1);
    all=a[2*n];
    dfs(1,n,1,0,0);
    for(int i=1;i<=n;i++) printf("%d ",ans[i]); puts("");
    return 0;
}

原文地址:https://www.cnblogs.com/Willendless/p/9563306.html