这是一个百度之星的资格赛第四题
题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500
题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。
咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上走的状态,所以加一维。
程序和注释如下:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<time.h>
#include<math.h>
#define inf 0x7fffffff
#define N 105
#define eps 1e-9
#define pi acos(-1.0)
#define P system("pause")
using namespace std;
int a[N][N],dp[N][N][3];//dp[][][0]:左->右 dp[][][1]:上->下 dp[][][2] 下->上
int n,m;
int fun(int a,int b,int c)
{
int t;
t = max(a,b);
return max(t,c);
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int t,z = 1;
scanf("%d",&t);
while(t--)
{
int i,j;
scanf("%d%d",&n,&m);
for(i = 0; i < n; i++)
for(j = 0; j < m; j++){
scanf("%d",&a[i][j]);
dp[i][j][0] = dp[i][j][1] = dp[i][j][2] = -inf;
}
dp[0][0][0] = dp[0][0][1] = dp[0][0][2] = a[0][0];
for(i = 1; i < n; i++)
dp[i][0][0] = dp[i][0][1] = dp[i][0][2] = dp[i-1][0][0] + a[i][0];
for(i = 1;i < m; i++)//遍历列
{
for(j = 0; j < n; j++)//左往右走
dp[j][i][0] = max(dp[j][i][0],fun(dp[j][i-1][0],dp[j][i-1][1],dp[j][i-1][2]) + a[j][i]);
for(j = 1; j < n; j++)//上往下走
dp[j][i][1] = max(dp[j][i][1],fun(dp[j-1][i][0],dp[j-1][i][1],dp[j-1][i][2]) + a[j][i]);
for(j = n-2; j >= 0; j--)//下往上走,但是这里要注意下,不能有dp[j+1][i][1],使得有通路
dp[j][i][2] = max(dp[j][i][2],max(dp[j+1][i][0],dp[j+1][i][2]) + a[j][i]);
}
// for(i = 0; i < n; i++){
//for(j = 0; j < m ;j++)
// cout<<fun(dp[i][j][0],dp[i][j][1],dp[i][j][2])<<" ";
//cout<<endl;}
printf("Case #%d:\n",z++);
printf("%d\n",fun(dp[0][m-1][0],dp[0][m-1][1],dp[0][m-1][2]));
}
// P;
return 0;
}