专栏文章

P9468

P9468题解参与者 5已保存评论 11

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
11 条
当前快照
1 份
快照标识符
@mipaz4ph
此快照首次捕获于
2025/12/03 09:03
3 个月前
此快照最后确认于
2025/12/03 09:03
3 个月前
查看原文
可以用 dp 做。
dpi,j,kdp_{i,j,k} 表示前 ii 个数选 jj 个进行填充,花 kk 步能达到的最大值。
状态是 O(n4)O(n^4) 的(转移步数会达到 O(n2)O(n^2) 量级),可以通过 n100n\leq 100 的数据。
在一个决策点上,你有两种选择:
  • 你要把 aia_i 换到 [1,j][1,j] 的区间里,此时换到 aja_j 是最优的。dpi1,j1,ki+j+aidpi,j,kdp_{i-1,j-1,k-i+j}+a_i \to dp_{i,j,k}
  • 不动 aia_idpi1,j,kdpi,j,kdp_{i-1,j,k}\to dp_{i,j,k}
最后的答案是 mindpn,f,ktk\min \limits_{dp_{n,f,k}\geq t}k
CPP
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int inf=1e16;
int dp[109][109][5009];
int N,F,T,ans=inf,presum=0;
int a[109];
signed main()
{
	cin>>N>>F>>T;
	for(int i=1;i<=N;i++) cin>>a[i];
	for(int i=1;i<=N;i++){
		for(int j=1;j<=min(i,F);j++){
			for(int k=0;k<=i*(i-1)/2;k++){
				dp[i][j][k]=dp[i-1][j][k];
				if(k-i+j>=0)
				dp[i][j][k]=max(dp[i-1][j-1][k-i+j]+a[i],dp[i][j][k]);
			}
		}
	}
	for(int k=0;k<=N*(N-1)/2;k++){
		if(dp[N][F][k]>=T) ans=min(ans,k);
	}
	if(ans==inf) cout<<"NO";
	else cout<<ans<<endl;
	return 0;
}

评论

11 条评论,欢迎与作者交流。

正在加载评论...