P1006 传纸条

链接

刚开始想的是两次01背包,把第一次走过的给记录下来。好像不太好记录,

参考了大佬的博客,数据范围不是很大,四维数组就可以了,

a,b第一个人走的,c,d代表第二个人

dp[a][b][c][d] = max{dp[a][b -1][c][d -1] , dp[a - 1][b][c -1][d],

                             dp[a][b -1][c -1][d],dp[a - 1][b][c][d -1]}+a[a][b] + a[c][d];

 只要保证纵坐标不一样就行,d = b + 1开始循环

最后输出是dp[n][m - 1][n - 1][m];

第一个人到第二个人只能往右或者往下走,所以到达的点是n,m-1

同理,第二个人到达的点是n-1,m;

如果卡的厉害,可以变为三维数组,怎么操作呢?

每次转移的时候,两个人走的步数是相等的,

枚举横坐标

k表示总的步数,

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 int a[55][55],dp[110][55][55];
 5 int n,m;
 6 
 7 int main(){
 8     //freopen("in","r",stdin);
 9     ios::sync_with_stdio(0);
10     cin >> n >> m;
11     for(int i = 1; i <= n; i++){
12         for(int j = 1; j <= m; j++){
13             cin >> a[i][j];
14         }
15     }
16     for(int k = 1; k <= n + m - 1; k++){
17         for(int i = 1; i <= n; i++){
18             for(int j = 1; j <= n; j++){
19                 if(k - i < 0 || k - j < 0)
20                     continue;
21                 dp[k][i][j] = max(max(dp[k - 1][i][j],dp[k - 1][i - 1][j - 1]),max(dp[k - 1][i][j - 1],dp[k - 1][i - 1][j])) + a[i][k - i + 1] + a[j][k - j + 1];
22                 if(i == j)
23                     dp[k][i][j] -=  a[i][k - i + 1];
24             }
25         }
26     }
27     cout << dp[n + m - 1][n][n] << endl;
28     return 0;
29 }
View Code
原文地址:https://www.cnblogs.com/xcfxcf/p/12774167.html