题解:P14328 [JOI2022 预选赛 R2] 糖 2 / Candies 2
Eternity_A · · 题解
题目传送门
题意
有
思路
首先想到定义
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e3+5;
int n,k,a[N],dp[N][N],ans;
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) dp[i][0]=a[i];
for(int i=1;i<=n;i++){
for(int j=0;j<i;j++){
for(int w=0;w<j;w++){
if(i-w>=k||w==0) dp[i][j]=max(dp[i][j],dp[j][w]+a[i]);
dp[i][j]=max(dp[i][j],dp[j][w]);
}
}
}
for(int i=0;i<n;i++) ans=max(ans,dp[n][i]);
cout<<ans;
return 0;
}
由于
我们可以用优先队列优化第三层枚举,用大根堆记录所有
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e3+5;
int n,k,a[N],dp[N][N],ans;
priority_queue<int> q[N];
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) dp[i][0]=a[i];
for(int i=1;i<=n;i++){
for(int j=0;j<i;j++){
if(!q[j].empty())
dp[i][j]=max(dp[i][j],q[j].top());
for(int w=0;w<=i-k||w==0;w++){
dp[i][j]=max(dp[i][j],dp[j][w]+a[i]);
}
q[i].push(dp[i][j]);
}
}
for(int i=0;i<n;i++) ans=max(ans,dp[n][i]);
cout<<ans;
return 0;
}
还是超时,继续优化。考虑继续用优先队列,每次枚举结束后存入
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e3+5;
int n,k,a[N],dp[N][N],ans;
priority_queue<int> q[N],q1[N];
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) dp[i][0]=a[i];
for(int i=1;i<=n;i++){
q1[i].push(dp[i][0]);
for(int j=0;j<i;j++){
if(!q[j].empty())
dp[i][j]=max(dp[i][j],q[j].top());
if(!q1[j].empty())
dp[i][j]=max(dp[i][j],q1[j].top()+a[i]);
q[i].push(dp[i][j]);
}
if(i+1-k>=0) for(int j=i;j>i+1-k;j--)
q1[j].push(dp[j][i+1-k]);
}
for(int i=0;i<n;i++) ans=max(ans,dp[n][i]);
cout<<ans;
return 0;
}
完结撒花!