当前位置:   article > 正文

牛客小白月赛 D.遗迹探险 - DP_题目描述: 小李是一名探险家,这天,他到了一个古代遗迹当中,但是这个遗迹的大门无

题目描述: 小李是一名探险家,这天,他到了一个古代遗迹当中,但是这个遗迹的大门无

题目描述

小Z是一名探险家。有一天,小Z误入了一个魔法遗迹。以下是该遗迹的具体组成:

1. 在 x 轴和 y 轴构成的平面上,满足在 1≤x≤n,1≤y≤m 的区域中(坐标(x,y)表示平面上的第x行的第y列),每个整数坐标 (x,y) 都有一个宝藏,坐标为(i,j)的宝藏的价值为ai,j(请注意,宝藏的价值可以为负)。换句话说,这个区域上的整点都有一个宝藏。
2. 对于任意一对点 (x1,y1) 和 (x2,y2),如果它们的横坐标相等,纵坐标之差为 1,则纵坐标小的点有一条道路可以到达纵坐标大的点,或者它们的纵坐标相等,横坐标之差为 1,则横坐标小的点有一条道路可以到达横坐标大的点。换句话说,(x,y)可以到达(x+1,y)或(x,y+1),反之不然。
3. 遗迹的入口在(1,1),出口在(n,m),小Z从入口进入后从出口离开,在移动的过程中他会将他所遇到的所有宝藏全部收集起来。


小Z想知道从进入到离开遗迹,他在离开遗迹时所能获得的宝藏的价值的和最大为多少

作为一个有智慧的探险家,小Z当然会解决这个问题。但是由于这个遗迹具有魔法,问题就变得不是那么简单了。

在小Z进入该遗迹前,遗迹的魔法发动,它会在若干个具有宝藏的位置生成一个传送门。若小Z所在的坐标有传送门,则他可以通过这个传送门到达其它任意一个具有传送门的位置(当然,他也可以选择不使用传送门),并且小Z在使用一次传送门后,所有的传送门都会消失。换句话说,小Z只能最多使用一次传送门。

该遗迹具有魔法,每当小Z离开某个整点,该整点就会重新生成一个价值为ai,ja_{i,j}ai,j​的宝藏。

小Z会进入TTT次该遗迹。请你帮助小Z计算出,对于每次进入遗迹,在给定传送门的坐标的情况下,他在离开遗迹时所能获得的宝藏的价值的和最大为多少

输入描述:

第一行包含两个正整数 n,m (2≤n≤103),变量的含义如题意所示。

接下来有n行,每行有m个整数,其中第i行第j列的数字代表坐标(i,j)的宝藏的价值ai,j (∣ai,j∣≤109)。

接下来有一个数字T (1≤T≤103),表示小Z进入的遗迹次数。

对于每次进入遗迹,第一行将给出一个整数k (2≤k≤5),表示传送门的个数。

接下来k行,每行有两个整数x,y (1≤x≤n,1≤y≤m),表示坐标(x,y)上有一个传送门。 数据保证传送门的坐标两两不同。

输出描述:

输出T行,第i行表示第i次进入该遗迹的宝藏的最大值。

示例1

输入

3 3
1 2 3
4 5 6
7 8 9
2
2
1 1
3 3
3
1 1
1 3
3 1

输出

58
41

 分析:

        计算两次dp,第一次计算从(1,1)到(i,j)的最大价值,第二次计算从(n,m)到(i,j)的最大价值(即任何一个点到(n,m)的最大价值),可以发现进入传送门可以多走一段路,那么最大价值就是不用传送门走到(n,m)的最大价值f(n,m),走到传送门的价值加上传送后(i,j)到(n,m)的最大值f(i1,j1)+g(i2,j2)。l另外需要预处理,注意存在负数情况。

代码:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef pair<int,int> pii;
  4. typedef long long ll;
  5. const int N=1010;
  6. ll a[N][N];
  7. ll f[N][N];
  8. ll g[N][N];
  9. int main()
  10. {
  11. ios::sync_with_stdio(false);
  12. cin.tie(0);
  13. cout.tie(0);
  14. int n,m;
  15. cin>>n>>m;
  16. for(int i=1;i<=n;i++)
  17. {
  18. for(int j=1;j<=m;j++)
  19. {
  20. cin>>a[i][j];
  21. }
  22. }
  23. memset(f,-0x3f,sizeof f);
  24. memset(g,-0x3f,sizeof g);
  25. f[0][1]=0;
  26. for(int i=1;i<=n;i++)
  27. {
  28. for(int j=1;j<=m;j++)
  29. {
  30. f[i][j]=max(f[i-1][j],f[i][j-1])+a[i][j];
  31. }
  32. }
  33. g[n][m+1]=0;
  34. for(int i=n;i>=1;i--)
  35. {
  36. for(int j=m;j>=1;j--)
  37. {
  38. g[i][j]=max(g[i+1][j],g[i][j+1])+a[i][j];
  39. }
  40. }
  41. int t;
  42. cin>>t;
  43. while(t--)
  44. {
  45. vector<pii> d;
  46. int k;
  47. cin>>k;
  48. while(k--)
  49. {
  50. int x,y;
  51. cin>>x>>y;
  52. d.push_back({x,y});
  53. }
  54. ll ans=f[n][m];
  55. for(int i=0;i<(int)d.size();i++)
  56. {
  57. for(int j=0;j<(int)d.size();j++)
  58. {
  59. if(i==j) continue;
  60. int x1=d[i].first;
  61. int x2=d[j].first;
  62. int y1=d[i].second;
  63. int y2=d[j].second;
  64. ans=max(ans,f[x1][y1]+g[x2][y2]);
  65. }
  66. }
  67. cout<<ans<<'\n';
  68. }
  69. }

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

闽ICP备14008679号