[关闭]
@Acqua 2019-02-23T08:39:32.000000Z 字数 1873 阅读 931

HDU5693 D Game(Feb. 22th, 2019) 区间DP

动态规划

题目来源

题意

给定一个长度为的序列和个公差,如果能够在序列中找到一个连续的、公差为给定公差的等差数列(长度大于1),就可以把整个数列都从序列中删掉。求最大删除数量。

原理

设给定公差数组为
预处理出表示从开始,公差为的最长连续等差数列长度。
表示区间内最多可删掉的数量。
初始化:
对于区间,删除有多种情况(完备性证明:因为最终序列将被分解为长度为2(最小的偶数)或3(满足题意的最小奇数)的子串,所以以下枚举可以覆盖所有情况。
情况可以一起删除(前提:区间全部删除),则该区间可全部删除。
枚举断点
情况可以一起删除(前提:区间全部删除),则该区间可删除
情况可以一起删除(前提:区间全部删除),则该区间可删除
情况可以一起删除(前提:区间全部删除),则该区间可全部删除。
取上述所有答案(包括初始化)最大值。

反思

  1. 解题法则:平时做题不需要穷尽思维,半小时后写不出来就看标。但是这半小时需要完全解析题目结构与条件。找到时间与经验获取上的平衡。考试时采取最优得分策略。

代码

  1. // La Pluie
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7. const int N = 300 + 5;
  8. int a[N], il[N][N], dp[N][N];
  9. int main(){
  10. int T, n, m;
  11. scanf("%d", &T);
  12. while(T--){
  13. memset(dp, 0, sizeof(dp));
  14. memset(il, 0, sizeof(il));
  15. scanf("%d %d", &n, &m);
  16. for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
  17. for(int i = 1; i <= m; i++){
  18. int ecart;
  19. scanf("%d", &ecart);
  20. for(int j = 1; j < n; j++){
  21. for(int k = j + 1; k <= n; k++){
  22. if(a[k] - a[j] == ecart){
  23. il[j][k] = 1;
  24. }
  25. }
  26. }
  27. }
  28. for(int l = 1; l <= n; l++){
  29. for(int i = 1; i + l - 1 <= n; i++){
  30. int j = i + l - 1;
  31. dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
  32. if(il[i][j] && dp[i + 1][j - 1] == j - i - 1) dp[i][j] = j - i + 1; // 情况1
  33. for(int k = i + 1; k < j; k++){
  34. dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]); // 由于是取最大值,所以没有先后关系,所以合并dp[i][k]和dp[k+1][j]来更新答案的过程可以放在循环中
  35. if(il[i][k] && dp[i + 1][k - 1] == k - i - 1) dp[i][j] = max(dp[i][j], dp[i + 1][k - 1] + dp[k + 1][j] + 2); // 情况2
  36. if(il[k][j] && dp[k + 1][j - 1] == j - k - 1) dp[i][j] = max(dp[i][j], dp[i][k - 1] + dp[k + 1][j - 1] + 2); // 情况3
  37. if(il[i][k] && il[k][j] && a[j] - a[k] == a[k] - a[i] && dp[i + 1][k - 1] == k - i - 1 && dp[k + 1][j - 1] == j - k - 1) dp[i][j] = j - i + 1; // 情况4
  38. }
  39. }
  40. }
  41. printf("%d\n", dp[1][n]);
  42. }
  43. return 0;
  44. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注