[训练] 图的K步移动最大收获

题意: N*M(1<=N,M<=100)的方格图,每个方格值小于1e9,从起点x,y出发,K(小于1e9)步之内回到出发点,问最大的收获

 

思路:

首先我们假设最优的策略是找一条长度为 c 的路径到某一个点 ( xx , yy ) ,然后预留原路返回的步数 c ,将剩下的 k - 2c 步对着 ( xx , yy )和旁边的最大的一个格子进行反复横跳,可以获得最大值

那么处理的方法就是,创建记录到达 ( x , y ) 的最大收获数组 val[][] 以及相应所需要走的路径长度记录数组 sp[][] ,从起点开始BFS,对每一格的最大收获进行更新,一个格子的最大收获可以由四连块的方格的收获转移而来,将四联块的收获减去反复横跳获得的收获就能得到到达 ( xx , yy ) 的路径长度,然后去四联块中的最大值进行更新

时间复杂度大约是O(nm)

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 const int d[4][2]={1,0,-1,0,0,1,0,-1};
 6 int n,m,sx,sy;
 7 ll k,ans=0,res,ress;
 8 ll g[110][110],sp[110][110],val[110][110];
 9 struct pt{
10     int x,y,st;
11     ll val;
12     pt(int x,int y,int st,ll val):x(x),y(y),st(st),val(val){}
13 };
14 
15 int main(){
16     cin>>n>>m>>sx>>sy>>k;
17     for(int i=1;i<=n;++i){
18         for(int j=1;j<=m;++j){
19             scanf("%lld",&g[i][j]);
20         }
21     }
22     queue<pt> q;
23     q.push(pt(sx,sy,0,0));
24     memset(sp,0x3f,sizeof(sp));
25     sp[sx][sy]=0;
26     val[sx][sy]=0;
27     while(!q.empty()){
28         pt u=q.front();
29         q.pop();
30         ll tmp=0;
31         for(int k=0;k<4;++k)    tmp=max(tmp,g[u.x+d[k][0]][u.y+d[k][1]]);
32         ll res=max(val[u.x][u.y]-(k-2*sp[u.x][u.y])/2*(tmp+g[u.x][u.y])+g[u.x][u.y],0ll);
33         for(int i=0;i<4;++i){
34             int xx=u.x+d[i][0],yy=u.y+d[i][1];
35             if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&(xx!=sx||yy!=sy)){
36                 ll ttmp=0;
37                 for(int k=0;k<4;++k)   ttmp=max(ttmp,g[xx+d[k][0]][yy+d[k][1]]);
38                 if(res+(k-2*sp[u.x][u.y]-2)/2*(ttmp+g[xx][yy])+g[xx][yy]>val[xx][yy]){
39                     val[xx][yy]=res+(k-2*sp[u.x][u.y]-2)/2*(ttmp+g[xx][yy])+g[xx][yy];
40                     sp[xx][yy]=sp[u.x][u.y]+1;
41                     q.push(pt(xx,yy,sp[xx][yy],val[xx][yy]));
42                 }
43             }
44         }
45     }
46     for(int i=1;i<=n;++i){
47         for(int j=1;j<=m;++j){
48             if(!g[i][j]||sp[i][j]>k/2)    continue;
49             ans=max(ans,val[i][j]);
50         }
51     }
52     cout<<ans;
53     return 0;
54 }
View Code

 

posted @ 2020-03-31 22:32  JNzH  阅读(371)  评论(4编辑  收藏  举报