[CCF NOIP2008 T3]
给定一个 N*M 的矩阵A,每个格子中有一个整数。现在需要找到两条从左上角 (1,1) 到右下角 (N,M) 的路径,路径上的每一步只能向右或向下走。路径经过的格子中的数会被取走。两条路径不能经过同一个格子。求取得的数之和最大是多少。N,M≤50。
数据规模约定:
30%的数据满足:1<=m,n<=10
100%的数据满足:1<=m,n<=50
第一行有2个用空格隔开的整数n和m,表示有n行m列(1<=n,m<=50)。
接下来的n行是一个n*m的矩阵,每行的n个整数之间用空格隔开。
一个整数,表示答案。
3 3
0 3 9
2 8 5
5 7 0
34
状态:路径长度/当前走过的步数。
记当前的步数为i,当前的两个坐标分别为x1,y1、x2,y2。我们可以只用3个变量i,x1,x2,F[i,x1,x2] 代表当前状态(y1 = i + 2 - x1,y2 = i + 2 - x2)。
起始状态:F[0,1,1] = A[1,1]
目标状态:F[N+M-2,N,N] = A[N,N]
#include
#include
#include
#define maxn 55
using namespace std;
int f[maxn<<1][maxn][maxn];
int a[maxn][maxn];
int n,m;
int max_ele(int a,int b,int c,int d){
if (b>a)
a = b;
if (c>a)
a = c;
if (d>a)
a = d;
return a;
}
int main(){
cin >> n >> m;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
cin >> a[i][j];
for (int k=1;k<=n+m-1;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++){
if (k-i+1<1 || k-j+1<1)
continue;
f[k][i][j] = max_ele(f[k-1][i][j],f[k-1][i-1][j-1],f[k-1][i][j-1],f[k-1][i-1][j]) + a[i][k-i+1] + a[j][k-j+1];
if (i==j)
f[k][i][j]-=a[i][k-i+1];
}
cout << f[n+m-1][n][n] << endl;
return 0;
}
int n,m;
int A[maxn][maxn];
int F[maxn<<1][maxn][maxn];
int max3(int a, int b, int c, int d){
if(b > a) a = b;
if(c > a) a = c;
if(d > a) a = d;
return a;
}
int main(){
cin>>n>>m;
_rep(i,1,n)
_rep(j,1,m)
scanf("%d",&A[i][j]);
_rep(i,1,n+m-1)
_rep(x1,1,min(n-1,i))
_rep(x2,1,min(n-1,i)){
int y1 = i+2-x1, y2 = i+2-x2;
F[i][x1][x2] = max3(F[i-1][x1][x2],F[i-1][x1-1][x2-1],F[i-1][x1][x2-1],F[i-1][x1-1][x2])+A[x1][y1]+A[x2][y2];
if(x1==x2) F[i][x1][x2] -= A[x1][x1];
}
cout<<F[n+m-2][n][n]<<endl;
return 0;
}
#include
#include
using namespace std;
int f[299][101][101],a[101][101],n,m,y_1,y_2;
int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
f[0][1][1]=a[1][1];
for (int i=0;i<=n+m-2;i++) {
for (int x_1=1;x_1<=n;x_1++)
for (int x_2=1;x_2<=n;x_2++) {
y_1=i+2-x_1;
y_2=i+2-x_2;
if (x_1==x_2) f[i+1][x_1][x_2]=max(f[i+1][x_1][x_2],f[i][x_1][x_2]+a[x_1][y_1+1]);
else f[i+1][x_1][x_2]=max(f[i+1][x_1][x_2],f[i][x_1][x_2]+a[x_1][y_1+1]+a[x_2][y_2+1]);//两个都往右走
if (x_1+1==x_2) f[i+1][x_1+1][x_2]=max(f[i+1][x_1+1][x_2],f[i][x_1][x_2]+a[x_1+1][y_1]);
else f[i+1][x_1+1][x_2]=max(f[i+1][x_1+1][x_2],f[i][x_1][x_2]+a[x_1+1][y_1]+a[x_2][y_2+1]);//一个往下走,一个往右走
if (x_1==x_2+1) f[i+1][x_1][x_2+1]=max(f[i+1][x_1][x_2+1],f[i][x_1][x_2]+a[x_2+1][y_2]);
else f[i+1][x_1][x_2+1]=max(f[i+1][x_1][x_2+1],f[i][x_1][x_2]+a[x_2+1][y_2]+a[x_1][y_1+1]);//一个往右走,一个往下走
if (x_1+1==x_2+1) f[i+1][x_1+1][x_2+1]=max(f[i+1][x_1+1][x_2+1],f[i][x_1][x_2]+a[x_1+1][y_1]);
else f[i+1][x_1+1][x_2+1]=max(f[i+1][x_1+1][x_2+1],f[i][x_1][x_2]+a[x_1+1][y_1]+a[x_2+1][y_2]);//都往右走
}
}
printf("%d",f[n+m-2][n][n]);
}