[BZOJ 3997] [TJOI 2015] 组合数学

3997: [TJOI2015]组合数学

Time Limit: 20 Sec
Memory Limit: 128 MB

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

【题解】

这题吧,用到一个性质:如果(i,j)与(i',j'),仅当(i',j')在(i,j)的左下方时,(i,j)无法到达(i',j')

那么,我们可以把矩阵翻转下。

然后dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+a[i][j])即可

 

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 #include<string.h>
 5 #include<algorithm>
 6 #include<math.h>
 7 #include<string>
 8 using namespace std;
 9 long long dp[1010][1010];
10 int a[1010][1010],n,m;
11 inline int maxx(int a,int b){return a>b?a:b;}
12 int read2() {
13     int x=0; int f=1;
14     char ch=getchar();
15     while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
16     while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
17     return x*f;
18 }
19 int main() {
20     int T; T=read2();
21     while(T--) {
22         memset(dp,0,sizeof(dp));
23         n=read2();m=read2();
24         for (int i=1;i<=n;++i)
25             for (int j=m;j>=1;--j) a[i][j]=read2();
26         for (int i=1;i<=n;++i)
27             for (int j=1;j<=m;++j)
28                 dp[i][j]=max(dp[i-1][j],max(dp[i][j-1],dp[i-1][j-1]+a[i][j]));
29         cout<<dp[n][m]<<endl;        
30     }
31     return 0;
32 }
View Code

 

 

 

posted @ 2015-06-12 11:00  TonyFang  阅读(440)  评论(0编辑  收藏  举报