zoukankan      html  css  js  c++  java
  • 方格取数+ 传纸条 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;
    }

     

  • 相关阅读:
    【ccf线上赛普及组 2020】
    【小总结】2020.3.6
    DP优化
    noip2012day2
    noip2012day1
    3.28真题
    数据结构总结
    noi online 普及组
    小总结
    20200229模拟赛
  • 原文地址:https://www.cnblogs.com/wondering-world/p/13279076.html
Copyright © 2011-2022 走看看