UVA1366-----Martian Mining------DP

本文出自:http://blog.csdn.net/dr5459

题目地址:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4112

题目地址:

给你一个N*M的地图,每个点都有A矿和B矿

A矿只能从左边往右边运输,B矿只能从上往下运输,中间不能拐弯,也不能间断

问你最多能采集的A和B之和

解题思路:

从题目可以发现如果在节点(i,j)上运输A的话,那么第i行的第1~j列只能运输A

同理,如果运输B的话,那么第j列的第1~i行只能运输B

给出状态表达式

定义:dp[i][j][0]表示如果在(i,j)上运输A的话的总和

dp[i][j][1]表示B的

那么转移方程就为:

dp[i][j][0] = max(dp[i-1][j][0],dp[i-1][j][1])+第i行第1~j列的A之和

dp[i][j][1] = max(dp[i][j-1][0],dp[i][j-1][1])+第j列第1~i行的B之和

行的和或者列的和预处理一下

最后的最优值就是max(dp[n][m][0],dp[n][m][1])


代码:

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

const int maxn = 510;

int dp[maxn][maxn][2];
int sum1[maxn][maxn];
int sum2[maxn][maxn];

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m) && n+m)
    {
        memset(dp,0,sizeof(dp));
        memset(sum1,0,sizeof(sum1));
        memset(sum2,0,sizeof(sum2));

        int tmp;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&tmp);
                sum1[i][j] = sum1[i][j-1]+tmp;
            }
        }

        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&tmp);
                sum2[i][j] = sum2[i-1][j]+tmp;
            }
        }

        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                dp[i][j][0] = max(dp[i-1][j][0],dp[i-1][j][1])+sum1[i][j];
                dp[i][j][1] = max(dp[i][j-1][0],dp[i][j-1][1])+sum2[i][j];
            }
        }

        printf("%d\n",max(dp[n][m][0],dp[n][m][1]));

    }
    return 0;
}


 

 

posted @ 2013-08-27 17:55  pangbangb  阅读(222)  评论(0编辑  收藏  举报