zoukankan      html  css  js  c++  java
  • P1004 [NOIP2000 提高组] 方格取数 题解(四维dp)

    题目链接

    题目大意

    给你一个n*n的方格图(n<=9),每个格子有权值

    某人从图的左上角的 A 点出发,可以向下行走,也可以向右走,直到到达右下角的 B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0)。
    此人从 A 点到 B 点共走两次,试找出 2 条这样的路径,使得取得的数之和为最大。

    题目思路

    如果只走一次很好,直接二维dp

    而走两次则可以想象为四维dp,用(f[i][j][k][l])表示第一个人走到(i,j),第二个人走到(k,l)的最优解

    注意(i,j)和(k,l)相同特判即可

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=10+5,mod=1e9+7;
    int dp[maxn][maxn][maxn][maxn];
    int a[maxn][maxn];
    int n;
    int main(){
        scanf("%d",&n);
        while(1){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            if(u+v+w==0) break;
            a[u][v]=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++){
                        dp[i][j][k][l]=max({dp[i-1][j][k-1][l],dp[i-1][j][k][l-1],dp[i][j-1][k-1][l],dp[i][j-1][k][l-1]});
                        if(i==k&&j==l){
                            dp[i][j][k][l]+=a[i][j];
                        }else{
                            dp[i][j][k][l]+=a[i][j]+a[k][l];
                        }
                    }
                }
            }
        }
        printf("%d
    ",dp[n][n][n][n]);
        return 0;
    }
    
    

    还有一个相似的题目

    题目链接

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long  ll;
    const int maxn=50+5,mod=1e9+7,inf=0x3f3f3f3f;
    int n,m;
    int a[maxn][maxn];
    int dp[maxn][maxn][maxn][maxn];
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&a[i][j]);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                for(int k=1;k<=n;k++){
                    for(int l=1;l<=m;l++){
                        if(i==k&&j==l&&(!(i==n&&j==m))){
                            dp[i][j][k][l]=-inf;
                        }else{
                            dp[i][j][k][l]=max({dp[i-1][j][k-1][l],dp[i][j-1][k-1][l],dp[i-1][j][k][l-1],dp[i][j-1][k][l-1]})+a[i][j]+a[k][l];
                        }
                    }
                }
            }
        }
        printf("%d
    ",dp[n][m][n][m]);
        return 0;
    }
    
    
  • 相关阅读:
    github fork项目后,代码更新
    UIScrollView的用法,属性
    调整屏幕亮度,调整字体大小
    iOS UIFont 字体名字大全
    ios 6以后,UILabel全属性
    oc中的各种遍历(迭代)方法
    判断app是否是第一次启动
    ios 显示代码块(show the code snippet library)
    ios 添加动画的方法
    添加app第一次启动页面
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/14317327.html
Copyright © 2011-2022 走看看