题目背景
又是一节平静的语文课
狗哥闲来无事,出来了这么一道题
题目描述
一个n*m的矩阵中,每个格子内有两种矿yeyenum和bloggium,并且知道它们在每个格子内的数量是多少。最北边有bloggium的收集站,最西边有 yeyenum 的收集站。现在要你在这些格子上面安装向北或者向西的传送带(每个格子只能装一种)。问最多能采到多少矿?
输入格式
第一行包含两个整数n,m,( 1 ≤ n ≤ 500, 1 ≤ m ≤ 500)。接下来n行m列,表示每个格子中可以传送到yeyenum的数量(小于1000),再接下来n行m列,表示每个格子中可以传送到bloggium的数量。n, m 同时为0结束。
输出格式
每组测试数据仅输出一个数,表示最多能采到的矿。
输入输出样例
输入 #1复制
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
输出 #1复制
98
说明/提示
传输过程中不能转弯,只能走直路。
思路
令dp[i][j]为以点(i,j)为右下角时的矩阵中最大采矿量。由于传送带不能转弯,所以在点(i,j)上,向左就会一直向左,向上就会一直向上。所以点(i,j)如果向左挖矿,可以从点(i,j-1)转移过来,而(i,j-1)也可以从点(i,j-2)转移过来,一直到(i,1)。同理,点(i,j)如果向上挖矿,可以从点(i-1,j)转移过来,而(i-1,j)也可以从点(i-2,j)转移过来,一直到(1,j)。
在挖矿的过程中,能影响dp[i][j]的值只有挖矿方向。用a[i][j]来记录向上的矿的前缀和,用b[i][j]来记录向左的矿的前缀和。则:
dp[i][j]=max(dp[i][j-1]+a[i][j],dp[i-1][j]+b[i][j])
答案为dp[n][m]。
#include <stdio.h>
#include <iostream>
#include <memory.h>
#define maxn 501
using namespace std;
int n,m,a[maxn][maxn],b[maxn][maxn],dp[maxn][maxn],inf;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
register int i,j,k,x,y;
cin>>n>>m;
while(n!=0 && m!=0)
{
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>a[i][j];
a[i][j]+=a[i][j-1];
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>b[i][j];
b[i][j]+=b[i-1][j];
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
dp[i][j]=max(dp[i-1][j]+a[i][j],dp[i][j-1]+b[i][j]);
}
}
cout<<dp[n][m]<<endl;
cin>>n>>m;
}
return 0;
}