码迷,mamicode.com
首页 > 其他好文 > 详细

方格取数+ 传纸条 noip2000 + noip2008 DP

时间:2020-07-10 15:28:27      阅读:97      评论:0      收藏:0      [点我收藏+]

标签:取数   clu   一点   char   pre   memset   条件   四种   i++   

方格取数

传纸条

 

两道题其实都差不多(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

标签:取数   clu   一点   char   pre   memset   条件   四种   i++   

原文地址:https://www.cnblogs.com/wondering-world/p/13279076.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!