概述
题目链接:http://codeforces.com/problemset/problem/467/C
题目意思:给出一条含有 n 个数的序列,需要从中找出 k 对,每对长度为 m 的子序列,使得 找出来的k对序列的总和相同。注意,同一个数不能在两个子序列中。
首先用了很暴力的做法,赛后发现过不了test 5 的时候,就知道需要用到 dp 来做了。看了这个人的提示:
其实看完这个状态转移方程,就觉得这题不太难了。
dp[i][j]: 前 i 个数中,选择 j pairs 可以获得的最大和。
那么对于第 i 个数来说,有不选和选择的两种情况。如果不选第 i 这个数 ,即dp[i-1][j],表示前 i 个数,选择 j pairs 获得的最大和 = 前i-1个数中选择 j pairs 可以获得的最大和;如果选第 i 个数,状态就转移到 dp[i-m][j-1] + sum[i] - sum[i-m],这个 sum[i]- sum[i-m] 会成为新的一个pair,前面那个第 i-m 个数就不要选。
虽然运行时间有点慢,但好在非常容易理解。
![](https://file2.kaopuke.com:8081/files_image/2023062420/202306242049079148358.gif)
![](https://file2.kaopuke.com:8081/files_image/2023062420/202306242049075788535.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 typedef long long ll; 8 const int maxn = 5000 + 10; 9 ll sum[maxn], dp[maxn][maxn], p; 10 11 int main() 12 { 13 int n, m, k; 14 while (scanf("%d%d%d", &n, &m, &k) != EOF) 15 { 16 scanf("%lld", &p); 17 sum[1] = p; 18 for (int i = 2; i <= n; i++) 19 { 20 scanf("%lld", &p); 21 sum[i] = sum[i-1] + p; 22 } 23 memset(dp, 0, sizeof(dp)); 24 dp[m][1] = sum[m]; 25 for (int j = 1; j <= k; j++) 26 { 27 for (int i = m+1; i <= n; i++) 28 { 29 dp[i][j] = max(dp[i-1][j], dp[i-m][j-1]+sum[i]-sum[i-m]); 30 } 31 } 32 printf("%lldn", dp[n][k]); 33 } 34 return 0; 35 }
转载于:https://www.cnblogs.com/windysai/p/3985252.html
最后
以上就是矮小猎豹为你收集整理的codeforces 467C.George and Job 解题报告的全部内容,希望文章能够帮你解决codeforces 467C.George and Job 解题报告所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复