传纸条
http://www.rqnoj.cn/Problem_400.html
dp[x1][y1][x2][y2]=max(dp[x1-1][y1][x2-1][y2],dp[x1-1][y1][x2][y2-1], dp[x1][y1-1][x2-1][y2],dp[x1][y1-1][x2][y2-1])+map[x1][y1]; if(x1!=x2 || y1!=y2) dp[x1][y1][x2][y2] += map[x2][y2];
#include<cstdio> #include<iostream> #include<cstring> #define MAXN 52 using namespace std; int dp[MAXN][MAXN][MAXN][MAXN],map[MAXN][MAXN]; int Max(int a,int b){ return a>b?a:b; } int max(int a,int b,int c,int d){ int t1=Max(a,b); int t2=Max(c,d); return Max(t1,t2); } int main() { freopen("input.txt","r",stdin); int m,n,i,j,x1,y1,x2,y2; while(scanf("%d %d",&m,&n)!=EOF){ for(i=1; i<=m; ++i){ for(j=1; j<=n; ++j) scanf("%d",&map[i][j]); } memset(dp,0,sizeof(dp)); for(x1=1; x1<=m; ++x1){ for(y1=1; y1<=n; ++y1){ for(x2=1; x2<=m; ++x2){ for(y2=1; y2<=n; ++y2){ dp[x1][y1][x2][y2]=max(dp[x1-1][y1][x2-1][y2],dp[x1-1][y1][x2][y2-1], dp[x1][y1-1][x2-1][y2],dp[x1][y1-1][x2][y2-1])+map[x1][y1]; if(x1!=x2 || y1!=y2) dp[x1][y1][x2][y2] += map[x2][y2]; } } } } printf("%d\n",dp[m][n][m][n]); } return 0; }
由于只能走右或下,所以坐标满足x+y=k。这样就能降低维数为3维,方程(核心代码):
// 核心代码 dp[k][x1][x2]=max(dp[k-1][x1][x2],dp[k-1][x1-1][x2-1], dp[k-1][x1-1][x2],dp[k-1][x1][x2-1])+map[x1][y1]; if(x1!=x2 || y1!=y2) dp[k][x1][x2] += map[x2][y2];
AC代码:
#include<cstdio> #include<iostream> #include<cstring> #define MAXN 52 using namespace std; int dp[MAXN*2+1][MAXN][MAXN],map[MAXN][MAXN]; int Max(int a,int b){ return a>b?a:b; } int max(int a,int b,int c,int d){ int t1=Max(a,b); int t2=Max(c,d); return Max(t1,t2); } int main() { // freopen("input.txt","r",stdin); int m,n,i,j,k,x1,y1,x2,y2; while(scanf("%d %d",&m,&n)!=EOF){ for(i=1; i<=m; ++i){ for(j=1; j<=n; ++j) scanf("%d",&map[i][j]); } memset(dp,0,sizeof(dp)); for(k=1; k<=n+m-1; ++k){ for(x1=1; x1<=k; ++x1){ for(x2=1; x2<=k; ++x2){ y1=k+1-x1; y2=k+1-x2; dp[k][x1][x2]=max(dp[k-1][x1][x2],dp[k-1][x1-1][x2-1], dp[k-1][x1-1][x2],dp[k-1][x1][x2-1])+map[x1][y1]; if(x1!=x2 || y1!=y2) dp[k][x1][x2] += map[x2][y2]; } } } printf("%d\n",dp[m+n-1][m-1][m]); } return 0; }
和传纸条类似
四维数组方法:
#include<cstdio> #include<iostream> #include<cstring> #define MAXN 52 using namespace std; int dp[MAXN][MAXN][MAXN][MAXN],map[MAXN][MAXN]; int Max(int a,int b){ return a>b?a:b; } int max(int a,int b,int c,int d){ int t1=Max(a,b); int t2=Max(c,d); return Max(t1,t2); } int main() { // freopen("input.txt","r",stdin); int n,i,j,x1,y1,x2,y2; while(scanf("%d",&n)==1){ for(i=1; i<=n; ++i){ for(j=1; j<=n; ++j) scanf("%d",&map[i][j]); } memset(dp,0,sizeof(dp)); for(x1=1; x1<=n; ++x1){ for(y1=1; y1<=n; ++y1){ for(x2=1; x2<=n; ++x2){ for(y2=1; y2<=n; ++y2){ dp[x1][y1][x2][y2]=max(dp[x1-1][y1][x2-1][y2],dp[x1-1][y1][x2][y2-1], dp[x1][y1-1][x2-1][y2],dp[x1][y1-1][x2][y2-1])+map[x1][y1]; if(x1!=x2 || y1!=y2) dp[x1][y1][x2][y2] += map[x2][y2]; } } } } printf("%d\n",dp[n][n][n][n]); } return 0; }
2.三维数组方法:
#include<iostream> #include<cstdio> #include<cstring> #define MAXN 32 using namespace std; int dp[MAXN*2+1][MAXN][MAXN], map[MAXN][MAXN]; int max(int a,int b,int c,int d){ int t1=a>b?a:b; int t2=c>d?c:d; return t1>t2?t1:t2; } int main() { int n,i,j,k,x1,x2,y1,y2; while(scanf("%d",&n)!=EOF){ for(i=1; i<=n; ++i){ for(j=1; j<=n; ++j) scanf("%d",&map[i][j]); } memset(dp,0,sizeof(dp)); for(k=1; k<=2*n-1; ++k){ for(x1=1; x1<=k; ++x1){ for(x2=1; x2<=k; ++x2){ y1 = k+1-x1; y2 = k+1-x2; dp[k][x1][x2] = max(dp[k-1][x1][x2],dp[k-1][x1-1][x2-1], dp[k-1][x1-1][x2],dp[k-1][x1][x2-1])+map[x1][y1]; if(x1!=x2 || y1!=y2) dp[k][x1][x2] += map[x2][y2]; } } } printf("%d\n",dp[k-1][n-1][n]); } return 0; }