方格取数+ 传纸条 noip2000 + noip2008 DP
Posted wondering-world
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了方格取数+ 传纸条 noip2000 + noip2008 DP相关的知识,希望对你有一定的参考价值。
两道题其实都差不多(DP方程都一样), 所以讲限制条件稍微多一点的传纸条。
首先,对题目进行翻译,我们完全可以把所谓来回,看做两次只能往右往下的完全不重复路线。
我们设 $f_{i,j,k,l}$ 表示第一次走到点 $(i , j)$ ,第二次走到点 $(k, l)$ 的最大和。
对于每一步有四种情况:
1.第一张纸条向下传,第二张纸条向下传;
2.第一张纸条向下传,第二张纸条向右传;
3.第一张纸条向右传,第二张纸条向下传;
4.第一张纸条向右传,第二张纸条向右传;
所以,我们就得到了状态转移方程
$f_{i,j,k,l}$ $=$ $max(f_{i-1,j,k-1,l} , f_{i-1,j,k,l-1}, f_{i,j-1,k-1,l}, f_{i,j-1,k,l-1}) + a_{i,j} + a_{k,l}$;
注意,在循环的时候,$l$应从 $j + 1$ 开始循环,只有这样才能确保两条线路不交叠,详情请手摸
(当然,如果您执意要从$1$开始,只需要在重复的时候判断并将状态减去$a_{i,j}$即可)
P1004 方格取数:
#include <bits/stdc++.h> using namespace std; #define N 10 inline int read(){ int x = 0, s = 1; char c = getchar(); while(!isdigit(c)){ if(c == ‘-‘)s = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + (c ^ ‘0‘); c = getchar(); } return x * s; } int f[N][N][N][N]; int a[N][N]; inline int max_ele(int a, int b, int c, int d){ int sum = a; if(b > sum) sum = b; if(c > sum) sum = c; if(d > sum) sum = d; return sum; } int main(){ int n = read(); memset(a, 0, sizeof(a)); int x = 666, y = 666, w = 666; while(x && y && w){ x = read(), y = read(), w = read(); a[x][y] = w; } for(int i = 1;i <= n; i++) for(int j = 1;j <= n; j++) for(int k = 1;k <= n; k++) for(int l = 1;l <= n; l++){ f[i][j][k][l] = max_ele(f[i-1][j][k-1][l], f[i-1][j][k][l-1], f[i][j-1][k-1][l], f[i][j-1][k][l-1]) + a[i][j] + a[k][l]; if(i == k && l == j) f[i][j][k][l] -= a[i][j]; } cout << f[n][n][n][n] << endl; return 0; }
P1006 传纸条:
#include <bits/stdc++.h> using namespace std; #define N 60 inline int read(){ int x = 0, s = 1; char c = getchar(); while(!isdigit(c)){ if(c == ‘-‘)s = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + (c ^ ‘0‘); c = getchar(); } return x * s; } int f[N][N][N][N]; int n, m; int a[N][N]; inline int max_element(int a, int b, int c, int d){ int sum = a; if(b > sum) sum = b; if(c > sum) sum = c; if(d > sum) sum = d; return sum; } int main(){ n = read(), m = read(); for(int i = 1;i <= n; i++) for(int j = 1;j <= m; j++) a[i][j] = read(); for(int i = 1;i <= n; i++) for(int j = 1;j <= m; j++) for(int k = 1;k <= n; k++) for(int l = j + 1;l <= m;l++) f[i][j][k][l] = max_element(f[i-1][j][k-1][l], f[i-1][j][k][l-1], f[i][j-1][k-1][l], f[i][j-1][k][l-1]) + a[i][j] + a[k][l]; cout << f[n][m-1][n-1][m] << endl; return 0; }
以上是关于方格取数+ 传纸条 noip2000 + noip2008 DP的主要内容,如果未能解决你的问题,请参考以下文章
Luogu1006 传纸条 与 Luogu P2045方格取数加强版 (费用流)
动态规划数字三角形模型 AcWing 1027. 方格取数 275. 传纸条
动态规划数字三角形模型 AcWing 1027. 方格取数 275. 传纸条