3997: [TJOI2015]组合数学
Time Limit: 20 SecMemory 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 }
时间: 2024-10-30 11:15:32