POJ 2948 Martian Mining

题意:如下图,有一种n*m的网格,每个格子里可能分别有两种矿物a[i][j]和b[i][j],在网格的上边和左边分别有这两种矿物的收集站。对每个网格,可以建立向上或者向左的传送带,将该格所有矿物传送。但是,传送带不能变方向,否则变方向之前的矿物会从传送带上掉落下来。比如,矿物如果从(i,j)传送到(i,j-1),再传送到(i-1,j-1),就会掉落。问最终能收集到的矿物最多为多少(两种矿物数量之和)。

解法:首先,对于第(i,j)格,如果它向左传送,则应该让(i,0), (i,1)...(i,j-1)都向左传送。向上同理。

   设d[i][j][0]表示第(i,  j)格向左传送的情况下,矩形(0,0)-(i,j)所能收集到最多的矿石数,d[i][j][1]表示第(i,  j)格向上传送的情况下,矩形(0,0)-(i,j)所能收集到最多的矿石数。设wes[i][j]表示收集点在左边的矿石(i,0),(i,1)...(i,j)格共有多少,nor[i][j]表示收集点在上边的矿石(0,j),(1,j),(2,j)...(i,j)格共有多少。

   wes和nor数组递推易求,d数组的状态转移方程为:d[i][j][0] = wes[i][j] + max(d[i-1][j][0], d[i-1][j][1]),d[i][j][1] = nor[i][j] + max(d[i][j-1][0], d[i][j-1][1])。

tag:网格类dp

 1 /*
 2  * Author:  Plumrain
 3  * Created Time:  2013-11-18 17:03
 4  * File Name: DP-POJ-2948.cpp
 5  */
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 
10 using namespace std;
11 
12 #define CLR(x) memset(x, 0, sizeof(x))
13 
14 int n, m;
15 int d[505][505][2];
16 int x[505][505][2];
17 int nor[505][505], wes[505][505];
18 
19 void init()
20 {
21     for (int t = 0; t < 2; ++ t)
22         for (int i = 0; i < n; ++ i)
23             for (int j = 0; j < m; ++ j)
24                 scanf ("%d", &x[i][j][t]);
25 
26     CLR (nor); CLR (wes);
27     for (int i = 0; i < n; ++ i)
28         for (int j = 0; j < m; ++ j){
29             wes[i][j] = (j ? x[i][j][0]+wes[i][j-1] : x[i][j][0]);
30             nor[i][j] = (i ? x[i][j][1]+nor[i-1][j] : x[i][j][1]);
31         }
32 }
33 
34 int DP()
35 {
36     CLR (d);
37     d[0][0][0] = x[0][0][0]; d[0][0][1] = x[0][0][1];
38     for (int i = 0; i < n; ++ i)
39         for (int j = 0; j < m; ++ j){
40             if (!i && !j) continue;
41             d[i][j][0] = wes[i][j];
42             if (i)
43                 d[i][j][0] += max(d[i-1][j][0], d[i-1][j][1]);
44             d[i][j][1] = nor[i][j];
45             if (j)
46                 d[i][j][1] += max(d[i][j-1][0], d[i][j-1][1]);
47         }
48     return max(d[n-1][m-1][0], d[n-1][m-1][1]);
49 }
50 
51 int main()
52 {
53     while (scanf ("%d%d", &n, &m) != EOF && n){    
54         init();
55         printf ("%d
", DP());        
56     }
57     return 0;
58 }
View Code
------------------------------------------------------------------
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。
原文地址:https://www.cnblogs.com/plumrain/p/POJ_2948.html