• 方格取数


    题目链接http://noi.openjudge.cn/ch0206/8786/

    描述

    设有N*N的方格图(N<=10),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):< p="">

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

    输入输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。输出只需输出一个整数,表示2条路径上取得的最大的和。样例输入

    8
    2 3 13
    2 6 6
    3 5 7
    4 4 14
    5 2 21 
    5 6 4
    6 3 15
    7 2 14
    0 0 0

    样例输出

    67

    来源NOIP2000复赛 提高组 第四题

    (WA)原来想先取一次最优解,更新后,再去一次最优解。发现过不了。这是一种贪心,这两个局部最优解不一定是整体最优解。可能两个局部最优解不可能把整个带数的格子取完,但整体最优解可以。

    (AC)   后来查了一下,发现这个是一个多线程DP,同时模拟两个人走。

           dp[i][j][k][r]表示第一个人走到(i,j),第二个人走到(k,r)的最优解。其可由max(dp[i-1][j][k-1][r],dp[i][j-1][k][r-1]),dp[i][j-1][k-1][r],max(dp[i-1][j][k][r-1]) + {maps[i][j](两个人位置重合时)或 maps[i][j]+maps[k][r](两个人位置不重合时)}转移而来。

    WA:

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<vector>
    #define DEBUG(x) cout<<#x<<" = "<<x<<endl
    using namespace std;
    int N;
    int Matrix[15][15];
    int Len[15][15];
    void dfs(int i,int j,int l)
    {
        if(l==0)return ;
        if(Len[i+1][j]>Len[i][j+1])dfs(i+1,j,l-Matrix[i][j]);
        else dfs(i,j+1,l-Matrix[i][j]);
        if(Len[i][j]==l&&Matrix[i][j]!=0){
                Matrix[i][j]=0;
        }
    }
    int main()
    {
        scanf("%d",&N);
        int ans=0;
        while(true){
            int i,j,v;
            scanf("%d%d%d",&i,&j,&v);
            if(i==0)break;
            Matrix[i][j]=v;
        }
        Len[N][N]=Matrix[N][N];
        for(int k=N-1;k>=1 ;k-- ){
            Len[N][k]+=Len[N][k+1];
            Len[k][N]+=Len[k+1][N];
        }
        for(int i=N-1;i>=1 ;i-- ){
            for(int j=N-1;j>=1 ;j-- ){
                Len[i][j]=max(Len[i][j+1],Len[i+1][j])+Matrix[i][j];
            }
        }
        dfs(1,1,Len[1][1]);
        ans=Len[1][1];
        memset(Len,0,sizeof(Len));
        Len[N][N]=Matrix[N][N];
        for(int k=N-1;k>=1 ;k-- ){
            Len[N][k]+=Len[N][k+1];
            Len[k][N]+=Len[k+1][N];
        }
        for(int i=N-1;i>=1 ;i-- ){
            for(int j=N-1;j>=1 ;j-- ){
                Len[i][j]=max(Len[i][j+1],Len[i+1][j])+Matrix[i][j];
            }
        }
        ans+=Len[1][1];
        printf("%d
    ",ans);
    
    }
    View Code

    AC:

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<vector>
    #define DEBUG(x) cout<<#x<<" = "<<x<<endl
    int N;
    int Matrix[15][15];
    int maxLen[15][15][15][15];
    using namespace std;
    int main()
    {
    //    freopen("in.txt","r",stdin);
        scanf("%d",&N);
        while(true){
            int i,j,v;
            scanf("%d%d%d",&i,&j,&v);
            if(i==0)break;
            Matrix[i][j]=v;
        }
        maxLen[1][1][1][1]=Matrix[1][1];
        for(int i=1;i<=N ;i++ ){
            for(int j=1;j<=N ;j++ ){
                    for(int l=1;l<=N ;l++ ){
                        for(int m=1;m<=N ;m++ ){
                            int p1=max(maxLen[i-1][j][l-1][m],maxLen[i][j-1][l][m-1]);
                            int p2=max(maxLen[i][j-1][l-1][m],maxLen[i-1][j][l][m-1]);
                            int r=max(p1,p2);
                            if(i==l&&j==m)maxLen[i][j][l][m]=r+Matrix[i][j];
                            else {
                                maxLen[i][j][l][m]=r+Matrix[i][j]+Matrix[l][m];
                            }
                        }
                    }
            }
        }
        printf("%d
    ",maxLen[N][N][N][N]);
    }
    View Code

    还有一个问题比较迷,为什么是从这四个状态转移过来的dp[i-1][j][k-1][r],dp[i][j-1][k][r-1]),dp[i][j-1][k-1][r],max(dp[i-1][j][k][r-1]?

    参考文献

    https://blog.csdn.net/heyanbai/article/details/79519532

  • 相关阅读:
    Android的startActivityForResult()与onActivityResult()与setResult()参数分析,activity带参数的返回
    git stash 保存当前工作状态
    vim diff 的使用
    git pull 命令
    java 开发环境安装
    vim 处理换行符
    git 操作分支
    git 操作远程仓库地址
    vim 宏的使用
    Chrome 调试技巧
  • 原文地址:https://www.cnblogs.com/MalcolmMeng/p/9200935.html
Copyright © 2020-2023  润新知