当前位置:   article > 正文

hdu 6289 寻宝游戏_小q最近迷上了一款寻宝游戏,这款游戏中每局都会生成一个n\times m的网格地图,从上

小q最近迷上了一款寻宝游戏,这款游戏中每局都会生成一个n\times m的网格地图,从上

寻宝游戏

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 165    Accepted Submission(s): 34


Problem Description
小Q最近迷上了一款寻宝游戏,这款游戏中每局都会生成一个 的网格地图,从上往下依次编号为第 行到第 行,从左往右依次编号为第 列到第 列。每个格子上都有不同数量的金币,第 行第 列的格子上的金币数量为

小Q一开始位于 ,每次他可以往右或者往下走,每当他经过某个格子时,他就可以拿走这个格子上的所有金币。小Q不能走出这个地图,当小Q不能再行动时,游戏结束。显然当且仅当小Q位于 时,游戏才会结束。

一轮游戏的得分为这一轮中收集到的金币总量,而在游戏开始前,因为小Q是超级VIP用户,所以他有 次机会交换某两个格子中的金币数。这 次机会不一定要用完,请写一个程序帮助小Q在一轮内拿到尽可能多的金币。
 

Input
第一行包含一个正整数 ,表示测试数据的组数。

每组数据第一行包含三个整数 ,分别表示地图的长宽以及交换的次数。

接下来 行,每行 个整数 ,依次表示每个格子中金币的数量。
 

Output
对于每组数据,输出一行一个整数,即能收集到的金币数量的最大可能值。
 

Sample Input
 
 
2 3 4 0 1 2 3 4 9 8 7 6 5 4 7 2 5 5 1 9 9 9 0 0 0 0 9 0 0 0 0 0 0 0 0 0 9 0 0 9 0 9 9 9
 

Sample Output
 
 
34 81
 

Source



上为qls题解截图。

下边是我做题中的愚见:

题目一看就是DP,有一种从1,1到n,m的n^2的DP,然而这个多了k次交换,所以题目从2维DP变成了4维DP。

dp[i][j][p][q]:表示走到(i,j)位置必经之路上没拿了p个非必经之路上拿了q个。

状态转移方程:

dp[i][j][p][q] = max ( dp[i][j][p][q] , dp[i-1][j][p][q]+mp[i][j] );//从上边直接下来

dp[i][j][p][q] = max ( dp[i][j][p][q] , dp[i-1][j][p-1][q] );

dp[i][j][p][q] = max ( dp[i][j][p][q] , dp[i][j][p][q-r]+que[r] );

dp[i][j][p][q] = max ( dp[i][j][p][q] , dp[i][j-1][p][q]+mp[i][j] );

dp[i][j][p][q] = max ( dp[i][j][p][q] , dp[i][j-1][p-1][q] );


  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int Map[55][55];
  4. int dp[55][55][55][55];
  5. int a[55];
  6. int Index;
  7. int cmp(int a,int b)
  8. {
  9. return a>b;
  10. }
  11. int main()
  12. {
  13. int t;
  14. scanf("%d",&t);
  15. while(t--)
  16. {
  17. int n,m,k;
  18. scanf("%d%d%d",&n,&m,&k);
  19. for(int i=1;i<=n;i++)
  20. for(int j=1;j<=m;j++)
  21. scanf("%d",&Map[i][j]);
  22. memset(dp,-1,sizeof(dp));
  23. dp[1][1][0][0]=Map[1][1];//取了第一个
  24. dp[1][1][1][0]=0; //没取
  25. for(int i=1;i<=n;i++)//n*n*k*k*k
  26. {
  27.         for(int j=1;j<=m;j++)
  28. {
  29. a[0]=0;
  30. Index=0;
  31. for(int k=1;k<=m;k++)//是从当前点往前和上一行当前点往后
  32. {
  33. if(k<j)
  34. a[++Index]=Map[i][k];
  35. else if(k>j)
  36. a[++Index]=Map[i-1][k];
  37. }
  38. sort(a+1,a+Index+1,cmp); //从大到小排序 将那些不是必经之路上的点取出来
  39. for(int k=1;k<=Index;k++)//求个前缀和
  40. a[k]=a[k]+a[k-1];
  41. for(int p=0;p<=k;p++)
  42. {
  43. for(int q=0;q<=k;q++)
  44. {
  45. if(dp[i-1][j][p][q]!=-1) //从上边过来(经过的路上)
  46. dp[i][j][p][q]=max(dp[i][j][p][q],dp[i-1][j][p][q]+Map[i][j]);
  47. if(p>=1 && dp[i-1][j][p-1][q]!=-1)//考虑有个点取还是没取 比如前边的那个第一个点
  48. dp[i][j][p][q]=max(dp[i][j][p][q],dp[i-1][j][p-1][q]);
  49. }
  50. }
  51. for(int p=k;p>=1;p--)
  52. {
  53. for(int q=k;q>=0;q--)
  54. {
  55. for(int r=p;r>=1;r--)//有多少非必经之路的
  56. {
  57.     if(dp[i][j][q][p-r]!=-1 && p-r>=0)//取出来r个
  58. dp[i][j][q][p]=max(dp[i][j][q][p],dp[i][j][q][p-r]+a[r]);
  59. }
  60. }
  61. }
  62. for(int p=0;p<=k;p++)
  63. {
  64. for(int q=0;q<=k;q++)
  65. {
  66. if(dp[i][j-1][p][q]!=-1)
  67. dp[i][j][p][q]=max(dp[i][j][p][q],dp[i][j-1][p][q]+Map[i][j]);
  68. if(p>=1 && dp[i][j-1][p-1][q]!=-1)
  69. dp[i][j][p][q]=max(dp[i][j][p][q],dp[i][j-1][p-1][q]);
  70. }
  71. }
  72. }
  73. }
  74. int ans=0;
  75. for(int i=0;i<=k;i++)
  76. ans=max(ans,dp[n][m][i][i]);
  77. printf("%d\n",ans);
  78. }
  79. return 0;
  80. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/443321
推荐阅读
相关标签
  

闽ICP备14008679号