P9814 题解

P9814 题解

题面

原题传送门

思路

发现 \(n\leqslant3\times10^3,m\leqslant100\),所以允许 \(O(nm^2)\) 的做法。

\(dp_{i,j,k,0/1}\) 表示遍历到 \(a\) 数组的第 \(i\) 个位置,\(b\) 数组插了 \(j\) 位,\(b\) 数组选了 \(k\) 个数做贡献,\(a_i\) 选或不选的最大值。

首先贪心的,只要在一种情况下一个数可选可不选,(即选了不会影响其他数选或不选)选了显然更优。

\(b\) 数组是任意顺序插入的,所以可以从大到小排序插入。

则转移式有四种情况:

  1. 不插入 \(b_j\),不选 \(a_i\),那么 \(a_{i-1}\) 选或不选没有什么区别,于是 \(dp_{i,j,k,0}=\max(dp_{i-1,j,k,0},dp_{i-1,j,k,1})\)
  2. 不插入 \(b_j\),选 \(a_i\),那么 \(a_{i-1}\) 肯定不能选了,于是 \(dp_{i,j,k,1}=dp_{i-1,j,k,0}+a_i\)
  3. 插入 \(b_j\),并且选上 \(b_j\),则 \(a_i,a_{i-1}\) 不能选,于是 \(dp_{i,j,k,0}=\max(dp_{i,j,k,0},dp_{i-1,j-1,k-1,0}+b_k)\)
  4. 插入 \(b_j\),并且不选 \(b_j\),则 \(a_i,a_{i-1}\) 选了更优,于是 \(dp_{i,j,k,1}=\max(dp_{i,j,k,1},dp_{i-1,j-1,k,1}+a_i)\)

但是这还没完,\(b\) 完全非常有可能没有选完,而这个时候我们还要继续 dp。

  1. 不选 \(b_k\),那 \(b_{k-1}\) 选或不选也没有什么区别,于是 \(dp_{i,j,k,0}=\max(dp_{i-1,j-1,k,0},dp_{i-1,j-1,k,1})\)
  2. \(b_k\),那 \(b_{k-1}\) 肯定就不能选了,于是 \(dp_{i,j,k,1}=dp_{i-1,j-1,k-1,0}+b_k\)

于是我们终于做完了,怕空间爆的话 dp 数组开滚一下就行。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
//#define gc getchar
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#define ll long long
#define ni i&1
#define li i&1^1
using namespace std;
const int MN=3e3+5,MM=105;
ll n,m,a[MN],b[MM],dp[2][MM][MM][2],ans;
char buf[1<<23],*p1=buf,*p2=buf;
void write(ll n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll x=0,f=1;char ch=gc();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}return x*f;}
bool cmp(ll x, ll y){return x>y;}
int main(){
    //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    n=read();for(int i=1; i<=n; i++) a[i]=read();
    m=read();for(int i=1; i<=m; i++) b[i]=read();
    sort(b+1,b+1+m,cmp);
    for(int i=1; i<=n; i++) for(int j=0; j<=min((ll)i,m); j++) for(int k=0; k<=j; k++){
        dp[ni][j][k][0]=max(dp[li][j][k][0],dp[li][j][k][1]);
        dp[ni][j][k][1]=dp[li][j][k][0]+a[i];
        if(j&&k) dp[ni][j][k][0]=max(dp[ni][j][k][0],dp[li][j-1][k-1][0]+b[k]);
        if(j-1>=k) dp[ni][j][k][1]=max(dp[ni][j][k][1],dp[li][j-1][k][1]+a[i]);
        ans=max(ans,max(dp[ni][j][k][0],dp[ni][j][k][1]));
    }
    for(int i=n+1; i<=n+m; i++) for(int j=0; j<=min((ll)i,m); j++) for(int k=0; k<=j; k++){
        if(j) dp[ni][j][k][0]=max(dp[li][j-1][k][0],dp[li][j-1][k][1]);
        if(j&&k) dp[ni][j][k][1]=dp[li][j-1][k-1][0]+b[k];
        ans=max(ans,max(dp[ni][j][k][0],dp[ni][j][k][1]));
    }
    write(ans);putchar('\n');
    return 0;
}//250805
posted @ 2025-08-05 22:32  naroto2022  阅读(6)  评论(0)    收藏  举报