您的位置:首页 > 其它

【bzoj3997】[TJOI2015]组合数学

2017-09-03 20:10 561 查看
Description

给出一个网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走。问至少走多少次才能将财宝捡完。此对此问题变形,假设每个格子中有好多财宝,而每一次经过一个格子至多只能捡走一块财宝,至少走多少次才能把财宝全部捡完。

Input

第一行为正整数T,代表数据组数。

每组数据第一行为正整数N,M代表网格图有N行M列,接下来N行每行M个非负整数,表示此格子中财宝数量,0代表没有

Output

输出一个整数,表示至少要走多少次。

Sample Input

1

3 3

0 1 5

5 0 0

1 0 0

Sample Output

10

HINT

N<=1000,M<=1000.每个格子中财宝数不超过10^6

题解

结论题,我只能意会。当一个点在另一个点的左下角时,他们的路径是不会重复的,所以从左下角到右上角跑一个最长路DP

dp[i][j]=max(dp[i+1][j-1]+a[i][j],max(dp[i][j-1],dp[i+1][j]));

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<ctime>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#define mod 1000000009
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,a[1005][1005],dp[1005][1005];
void solve()
{
n=read();m=read();
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
a[i][j]=read();
for (int i=n;i;i--)
for (int j=1;j<=m;j++)
dp[i][j]=max(dp[i+1][j-1]+a[i][j],max(dp[i][j-1],dp[i+1][j]));
printf("%d\n",dp[1]
);
}
int main()
{
int Case=read();
while (Case--) solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: