Labyrinth
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 152 Accepted Submission(s): 76
每组数据的第一行输入两个正整数m,n(m<=100,n<=100)。接下来的m行,每行n个整数,分别代表相应格子中能得到金币的数量,每个整数都大于等于-100且小于等于100。
每组测试数据输出一行,输出一个整数,代表根据最优的打法,你走到右上角时可以获得的最大金币数目。
2 3 4 1 -1 1 0 2 -2 4 2 3 5 1 -90 2 2 1 1 1 1
Case #1: 18 Case #2: 4
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4826
思路:搜索的话,搜索空间太大,耗时太多。
DP:问题有最优子结构的性质。题目中说可以向右或者上下走,但是不能重复走,所以从左向右更新,但是只能从上往下或者从下往上单向更新。
代码有点冗余,可能是因为不经常练习。
还有就是dp数组可以开成一维的。
#include <bits/stdc++.h>
using namespace std;
#define MAXN 101
#define MIN -110000000
int dp[MAXN][MAXN] ;
int arr[MAXN][MAXN];
int main(){
int N;
cin >>N;
int NN = N ;
while (N-- > 0){
int m , n ;
cin>>m>>n;
for(int i =0 ; i < m ; ++i){
for(int j = 0 ; j < n ; ++j){
cin>>arr[i][j];
dp[i][j] = MIN;
}
}
for (int j = 0 ; j < n ;++j)
{
if (j!=0 && j != n-1){
for (int i = 0 ; i < m ; ++i){
dp[i][j] = dp[i][j-1]+arr[i][j];
if(i != 0)
dp[i][j] = max(dp[i][j] ,dp[i-1][j]+arr[i][j]);
}
int dptemp[MAXN];
for (int i = m-1 ; i >= 0 ; --i){
dptemp[i] = dp[i][j-1]+arr[i][j];
if (i!=m-1){
dptemp[i] = max(dptemp[i] , dptemp[i+1]+arr[i][j]);
}
}
for (int i = 0 ; i < m ; ++i)
dp[i][j] = max(dp[i][j] , dptemp[i]);
}else {
if (j==0){
dp[0][0] =arr[0][0];
for (int i = 0 ; i < m ; ++i){
//dp[i][j] = max(dp[i][j-1]+arr[i][j];
if(i != 0)
dp[i][j] = max(dp[i][j] ,dp[i-1][j]+arr[i][j]);
}
}else{
for (int i = m-1 ; i >= 0 ; --i){
dp[i][j] = max(dp[i][j-1]+arr[i][j],dp[i][j]);
if(i != m-1)
dp[i][j] = max(dp[i][j] ,dp[i+1][j]+arr[i][j]);
}
}
}
}
// for (int i = 0 ; i < m ; ++i){
// for(int j =0 ; j < n ; ++j){
// cout<<dp[i][j];
// if (j==n-1)
// cout<<endl;
// else
// cout<<" ";
// }
// }
cout<<"Case #"<<NN-N<<":"<<endl;
cout<<dp[0][n-1]<<endl;
}
}