zoukankan      html  css  js  c++  java
  • Restart-洛谷2386

      鉴于本题题目太丑,所以没放在标题上(叫作 狗哥采矿 .........)。

     题目摘录:

    题目背景 又是一节平静的语文课 狗哥闲来无事,出来了这么一道题

    题目描述 一个n*m的矩阵中,每个格子内有两种矿yeyenum和bloggium,并且知道它们在每个格子内的数量是多少。最北边有bloggium的收集站,最西边有 yeyenum 的收集站。现在要你在这些格子上面安装向北或者向西的传送带(每个格子只能装一种)。问最多能采到多少矿?

    输入输出格式 输入格式: 第一行包含两个整数n,m,( 1 ≤ n ≤ 500, 1 ≤ m ≤ 500)。接下来n行m列,表示每个格子中可以传送到yeyenum的数量(小于1000),再接下来n行m列,表示每个格子中可以传送到bloggium的数量。n, m 同时为0结束。 输出格式: 每组测试数据仅输出一个数,表示最多能采到的矿。

    输入输出样例 输入样例: 4 4 0 0 10 9 1 3 10 0 4 2 1 3 1 1 20 0 10 0 0 0 1 1 1 30 0 0 5 5 5 10 10 10 0 0 输出样例 98

    说明: 传输过程中不能转弯,只能走直路。

    题目大意:有一个n*m的网格,每个格点有两个值(代表两种东西)。可以在某个格点上只能修一条向上或者向左的路,路的长度为1,然后可以将该格点上的东西运到该格点上的路连通的格点。一种东西只能向左运,另一种只能向上,运出网格即可获得该物品,运输过程中不能转弯,求最大价值(两种物品价值和)。

    思路:动态规划,定义f[i][j]为在以(i,j)为右下角的子矩阵中的最大采矿量,由题意我们可知,如果(i,j)是向左转移矿,那么(i,j−1),一定也是向左(i,j−2)一直到(i,1)都是向左,同理如果(i,j)是向上转移矿,那么(i−1,j),一定也是向上(i−2,j)一直到(1,j)都是向左。这就可以其实我们用前缀和去维护一段区间的采矿量。
    在转移时,我们只关心当前(i,j)的采矿方向。设sum[i][j][0]为向上的前缀和,sum[i][j][1]为向左的前缀和,那么转移方程为f[i][j]=max(f[i-1][j]+sum[i][j][1],f[[i][j-1]+sum[i][j][0]).

    举个栗子,当推完f[2][2],要推f[2][3]时,f[2][3]就是 max( f[1][3] 加上 f[2][1]到f[2][3])  , (f[2][2] 加上 f[1][3]到f[2][3]),与其他的无关。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 struct edg{
     4     int x,y;
     5 }a[510][510];
     6 int n,m,f[510][510],sum[501][501][2];
     7 int main()
     8 {
     9     while(1){
    10         scanf("%d%d",&n,&m);
    11         if(n==0&&m==0)
    12             break;
    13         for(int i=1;i<=n;i++)
    14             for(int j=1;j<=m;j++)
    15                 scanf("%d",&a[i][j].x);
    16         for(int i=1;i<=n;i++)
    17             for(int j=1;j<=m;j++)
    18                 scanf("%d",&a[i][j].y);
    19         for(int i=1;i<=n;i++)
    20             for(int j=1;j<=m;j++){
    21                 sum[i][j][0]=sum[i-1][j][0]+a[i][j].y;
    22                 sum[i][j][1]=sum[i][j-1][1]+a[i][j].x;
    23             }
    24         for(int i=1;i<=n;i++)
    25             for(int j=1;j<=m;j++)
    26                 f[i][j]=max(f[i-1][j]+sum[i][j][1],f[i][j-1]+sum[i][j][0]);
    27         printf("%d
    ",f[n][m]);
    28     }
    29     return 0;
    30 }

  • 相关阅读:
    剔除数组中重复对象
    2018湖南省高中数学联赛(A)试题
    向量与三角
    阿波罗尼斯圆
    2019高考理科数学(天津卷)
    转载Android常见错误(http://www.cnblogs.com/oklanyan/archive/2011/10/12/2208378.html)
    TCP/IP网络层谜云
    bitmap 设置图片尺寸,避免 内存溢出 OutOfMemoryError的优化方法(转载:http://tonyyu.iteye.com/blog/713256)
    ArcGIS for Android 离线数据编辑原理
    Android环境搭建(XP/Win7)转载http://www.cnblogs.com/oklanyan/archive/2011/10/14/2207339.html
  • 原文地址:https://www.cnblogs.com/Miroerwf/p/7955886.html
Copyright © 2011-2022 走看看