• LightOJ1036 A Refining Company(DP)


    题目大概说有一个n*m的格子地图,每个格子有铀或者镭矿。地图最北面的镭矿加工厂,最西面有铀矿加工厂,而要通过在格子里铺设由南向北(镭)或由东向西(铀)的轨道来送矿物到加工厂。一个格子只能铺设一种轨道,即要嘛运送铀要嘛运送镭,不同轨道也不能相交。现在知道地图上各个格子铀和镭的数量,问怎么铺设轨道使送到加工厂的矿物数量最多。

    • 首先明确要运送某一格子的镭矿到北面加工厂,这个轨道肯定是直直连续往上的;而铀矿同理,是水平连续向左的轨道。
    • 另外,因为获得的数量要最多,各个格子肯定都要铺设轨道,反证可知。
    • 然后可以发现,格子(i,j)怎样与格子(0,0)到格子(i-1,j-1)的围成的矩形所有格子的情况毫不相关,这样就考虑DP了:
      1. dp[0][i][j]表示格子(0,0)到格子(i,j)围成的矩形中,格子(i,j)铺设横轨道能获得的最大数量
      2. dp[1][i][j]表示格子(0,0)到格子(i,j)围成的矩形中,格子(i,j)铺设竖轨道能获得的最大数量

    转移:

      1. dp[0][i][j]就是从max(dp[0][i-1][j],dp[1][i-1][j])+sum(格子(i,0)的铀数量...格子(i,j)的铀数量)
      2. dp[1][i][j]同理
    • 而最后的结果就是max(dp[0][n-1][m-1],dp[1][n-1][m-1])
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int U[555][555],R[555][555],d[2][555][555];
     7 int main(){
     8     int t,n,m;
     9     scanf("%d",&t);
    10     for(int cse=1; cse<=t; ++cse){
    11         scanf("%d%d",&n,&m);
    12         for(int i=0; i<n; ++i){
    13             for(int j=0; j<m; ++j){
    14                 scanf("%d",&U[i][j]);
    15             }
    16         }
    17         for(int i=0; i<n; ++i){
    18             for(int j=0; j<m; ++j){
    19                 scanf("%d",&R[i][j]);
    20             }
    21         }
    22         memset(d,0,sizeof(d));
    23         d[0][0][0]=U[0][0];
    24         d[1][0][0]=R[0][0];
    25         for(int i=0; i<n; ++i){
    26             for(int j=0; j<m; ++j){
    27                 if(i==0 && j==0) continue;
    28                 if(i==0){
    29                     int sum=0;
    30                     for(int k=0; k<=j; ++k){
    31                         sum+=U[i][k];
    32                     }
    33                     d[0][i][j]=sum;
    34 
    35                     d[1][i][j]=max(d[0][i][j-1],d[1][i][j-1])+R[i][j];
    36                 }else if(j==0){
    37                     d[0][i][0]=max(d[0][i-1][0],d[1][i-1][0])+U[i][j];
    38 
    39                     int sum=0;
    40                     for(int k=0; k<=i; ++k){
    41                         sum+=R[k][j];
    42                     }
    43                     d[1][i][j]=sum;
    44                 }else{
    45                     int sum=0;
    46                     for(int k=0; k<=j; ++k){
    47                         sum+=U[i][k];
    48                     }
    49                     d[0][i][j]=max(d[0][i-1][j],d[1][i-1][j])+sum;
    50 
    51                     sum=0;
    52                     for(int k=0; k<=i; ++k){
    53                         sum+=R[k][j];
    54                     }
    55                     d[1][i][j]=max(d[0][i][j-1],d[1][i][j-1])+sum;
    56                 }
    57             }
    58         }
    59         printf("Case %d: %d
    ",cse,max(d[0][n-1][m-1],d[1][n-1][m-1]));
    60     }
    61     return 0;
    62 }
  • 相关阅读:
    康拓展开
    P6032 选择客栈 加强版 递推
    0923考试T3 二进制,位运算
    0922考试T3 dfs序 lca 线段树 树上问题
    0921考试T2
    0922考试T1
    P3934 [Ynoi2016]炸脖龙I 树状数组 扩展欧拉定理
    0922考试T4 区间DP
    P6834 [Cnoi2020]梦原 树状数组 期望DP
    UVA1364 Knights of the Round Table Tarjan求点双联通分量+二分图染色
  • 原文地址:https://www.cnblogs.com/WABoss/p/5659350.html
Copyright © 2020-2023  润新知