原题链接:
1032: http://210.44.14.31/problem/show/1032
1194: http://210.44.14.31/problem/show/1194
状态转移方程:
三维:
dp[k][i][j] = max(dp[k - 1][i][j], dp[k - 1][i - 1][j], dp[k - 1][i][j - 1], dp[k-1][i - 1][j - 1])+jz[i][k+2-i]+jz[j][k+2-j];
四维:
dp[i1][j1][i2][j2] = max(dp[i1 - 1][j1][i2 - 1][j2], dp[i1 - 1][j1][i2][j2 - 1], dp[i1][j1 - 1][i2 - 1][j2], dp[i1][j1 - 1][i2][j2 - 1]) + jz[i1][j1] + jz[i2][j2];
分析见代码。
四维:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
int dp[51][51][51][51];
int jz[52][52];
int max(int a, int b, int c, int d)//求四个数中的最大数。(三维法代码上的更快)
{
int x = a > b ? a : b;
int y = c > d ? c : d;
return x > y ? x : y;
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n;i++)
for (int j = 1; j <= m; j++)
scanf("%d",&jz[i][j]);
for (int i1 = 1; i1 <= n;i1++) //i1,j1代表第一个,i2,j2代表第二个。
for (int j1 = 1; j1 <= m;j1++)
for (int i2 = 1; i2 <= n;i2++)
for (int j2 = 1; j2 <= m; j2++)
{
dp[i1][j1][i2][j2] = max(dp[i1 - 1][j1][i2 - 1][j2], dp[i1 - 1][j1][i2][j2 - 1], dp[i1][j1 - 1][i2 - 1][j2], dp[i1][j1 - 1][i2][j2 - 1]) + jz[i1][j1] + jz[i2][j2];
if (i1 == i2&&j1 == j2) //重叠时减去一个
dp[i1][j1][i2][j2] -= jz[i1][j1];
}
cout << dp[n][m][n][m];//无换行
return 0;
}
三维:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
int dp[105][51][51];
int jz[52][52];
int max(int a, int b, int c, int d)//求四个数中的最大数
{
if (a >= b&&a >= c&&a >= d) return a;
else if (b >= c&&b >= d) return b;
else if (c >= d) return c;
else return d;
}
int main()
{
int n, m;
scanf_s("%d%d", &n, &m); //注意:虽然输入是 n,m 但矩阵是 m*n。。呵呵~
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf_s("%d", &jz[i][j]);
int sumbs = m + n - 2; //算出一共需要走多少步。(自己可以在演草纸上画一下,易得出)
for (int k = 1; k <= sumbs; k++) // 注意:k=i+向下走的步数-2 所以下文 k+2-i k+2-j 分别表示第一个向下走的步数和第二个向下走的步数
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
if (i != j&&k + 2 - i >= 1 && k + 2 - j >= 1) //1.保证不重叠 2.保证在范围内(k + 2 - i >= 1 && k + 2 - j >= 1也可不写,不写耗时间你懂~)
dp[k][i][j] = max(dp[k - 1][i][j], dp[k - 1][i - 1][j], dp[k - 1][i][j - 1], dp[k - 1][i - 1][j - 1]) + jz[i][k + 2 - i] + jz[j][k + 2 - j];
}
cout << dp[sumbs][n][n - 1];//易理解:dp[sumbs][n][n - 1]==dp[sumbs][n - 1][n]; 注意:本程序不包含第一个点(即jz[1][1])
return 0;
}