【DP专题】——洛谷P0170道路游戏

动规题。

传送门:GO


 

首先处理出前缀和。

s[i][j]表示时间为i时,在j点的金币前缀和,这个更新是沿着对角线来的。

假如机器人在第t秒,第j个位置上,下一次一定是(t+1,(j+1)%n)

设f[i][j]表示以上情况下的最大金币量,枚举行走步数,大致口胡得到:

f[i][j]=max(f[i][j],f[(i-k+n)%n][j-k]+s[(i-k+n)%n][k])

但是发现枚举的东西很多(位置,时间,跳跃步长),时间复杂度O(n^3)

所以可以不要第一维,因为p<=m,所以每次前进不会超过一圈,也就是更新某个位置的状态时,不会有后效性。

用f[i]表示时间为i时,能获得的最大金币量。

如果在某个位置j放了机器人,行走步长为k,修理机器人的钱用fix[i]表示,那么状态转移就是:

f[i]=max(f[i-k]-sum[i-k][j-k]-fix[j-k])+sum[i][j]

括号里的一坨用单调队列搞一下,取最大值即可。

(为什么普及组的题会考单调队列,wsl)

膜拜一下这位大大的题解:GO

 花了好久才看懂,但确实受益很多了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int read(){
 4     int f=1,x=0;
 5     char c=getchar();
 6     while(!isdigit(c)){
 7         if(c=='-') f=-1;
 8         c=getchar();
 9     }
10     while(isdigit(c)){
11         x=(x<<1)+(x<<3)+(c^48);
12         c=getchar();
13     }
14     return x*f;
15 }
16 const int N=1010;
17 int n,m,p;
18 int a[N][N];
19 int sum[N][N];
20 int fix[N];
21 int f[N];
22 struct node{
23     int val,idx;
24 };
25 deque<node> t[N];
26 int main(){
27     n=read();m=read();p=read();
28     for(int i=1;i<=n;i++){
29         for(int j=1;j<=m;j++){
30             a[j][i]=read();    
31         }
32     }
33     int j_=1;
34     for(int i=1;i<=m;i++){
35         for(int j=1;j<=n;j++){
36             if(j>1) j_=(j_==n?1:j_+1);
37             sum[i][j_]=sum[i-1][j_]+a[i][j];
38         }
39     }
40     for(int i=1;i<=n;i++){
41         fix[i]=read();
42     } 
43     node tmp;
44     j_=1;
45     int maxlas=0;
46     for(int i=1;i<=m;i++){
47         tmp.idx=i;
48         for(int j=1;j<=n;j++){
49             if(j>1) j_=(j_==n?1:j_+1);
50             while(!t[j_].empty()&&t[j_].front().idx+p<=i) t[j_].pop_front();
51             tmp.val=maxlas-fix[j]+a[i][j];
52             while(!t[j_].empty()&&tmp.val>=t[j_].back().val+sum[i][j_]-sum[t[j_].back().idx][j_]) t[j_].pop_back();
53             t[j_].push_back(tmp);
54             f[j]=max(maxlas-fix[j]+a[i][j],t[j_].front().val+sum[i][j_]-sum[t[j_].front().idx][j_]);
55         }
56         maxlas=-1e9;
57         for(int j=1;j<=n;j++) maxlas=max(maxlas,f[j]);
58     }
59     printf("%d",maxlas);
60     return 0;
61 } 
posted @ 2019-09-25 20:35  Nelson992770019  阅读(124)  评论(0编辑  收藏  举报