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; }