Blue Bridge Cup grid access Java Yan's DP analysis and general methods

First off topic

Digital triangle

Pick peanuts

Minimum toll

Title description :
There is an N×N grid. We fill in positive integers in some of the squares, and put the number 0 in other squares. As shown below:

Insert picture description here

Someone starts from A in the upper left corner of the figure, and can walk down or to the right until they reach point B in the lower right corner.

On the way he walks, he can take the number in the square (the square after taking it will become the number 0).

This person has walked twice from point A to point B. Try to find two such paths so that the sum of the numbers obtained is the largest.

Input format

The first line is an integer N, which represents an N×N grid graph.
Each next row has three integers, the first is the row number, the second is the column number, and the third is the number placed on the row and column.

The row and column numbers start from 1, and the row "0 0 0" means the end.

Output format

Output an integer that represents the largest sum obtained on the two paths.

data range

N≤10

Input sample:

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

Sample output:

67

Ideas

General method Four-dimensional dp

这个题要求的是走两遍,每次的最大值相加,选过的
方格值为0,一开始我想的是两次二维dp,选过的直接
为0,试验之后发现第二次的dp值为0,才想起来第一
此dp把所有的每格子可能的最大值全算出来了,也就是
说所有的格子都用过。
 于是网上看到的常见的是四维dp,大概思路是这样
 1.想象两个人在这个方格中走,每个人有一条路径,
 总的就是两条路径,dp[i][j][k][l]表示第一个人
 走到(i,j)这个格子的时候第二个走到(k,l)这
 个格子的时候的最大值,答案就是dp[N][N][N][N],
 正好表示第一个人走到(N,N)第二个人也走到了(N,N)
 正好是两条路径;
 
 2. 当两个人走到同一个格子的时候,格子的值只能加
 一次,还有就是第一个人走到(i,j)有两种方法:要
 么从上往下走走到了,要门从左往右走走到了,这样两
 个人就有了“四种”状态,取这四种状态的最大值,就是
 最后的答案;
 

Code


public class Main{
    
    
    public static void main(String[] args) {
    
    
        Scanner input=new Scanner(System.in);
        int N=input.nextInt();
        int [][]arr=new int[N+2][N+2];
        for(int i=1;i<=12;i++){
    
    
            int x=input.nextInt();
            int y=input.nextInt();
            arr[x][y]=input.nextInt();

        }
        int [][][][]dp=new int [N+1][N+1][N+1][N+1];
        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++){
    
    
                    //第一个和第二个都是从下往上来
                    //第一个从上往下第二个从左往右
                        int temp1=Math.max(dp[i-1][j][k-1][l],dp[i-1][j][k][l-1]);
                    //第一个左往右第二个从上往下
                    //第一个和第二个都是从左往右
                        int temp2=Math.max(dp[i][j-1][k-1][l],dp[i][j-1][k][l-1]);
                        dp[i][j][k][l]=Math.max(temp1,temp2)+arr[i][j];
                        //坐标不相等时加两次
                        if(i!=k&&j!=l) dp[i][j][k][l]+=arr[k][l];

                    }
                }
            }
        }
        System.out.println(dp[N][N][N][N]);

    }
}

Yan's DP analysis

The method y always talks about transforms a four-dimensional DP into a three-dimensional DP, because what we are looking for is to walk twice and it can be regarded as two people walking at the same time, and the same grid cannot be selected repeatedly, so the final result of walking at the same time and walking separately is the same.

Taking two routes at the same time, the sum of their abscissas and ordinates is the same. We set this sum to K. 因此(i,j)就可以表示为(i,K-i)dp[K][i1][i2] is 表示两个人从(1,1)分别走到(i1,K-i1)和(i2,K-i2)所有路径的最大值not easy to understand, so just go to two pictures
From y total algorithm improvement course

Insert picture description here
Then the code:

import java.util.Scanner;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner input=new Scanner(System.in);
        int N=input.nextInt();
        int [][]arr=new int[N+2][N+2];
        for(int i=1;i<=12;i++){
    
    
            int x=input.nextInt();
            int y=input.nextInt();
            int z=input.nextInt();
            if(x==0&&y==0&&x==0)
            {
    
    
                break;
            }
            else arr[x][y]=z;

        }
        //K表示横纵坐标之和走两条路,同时走所以x+y的值是一定的
        //当i1==i2, 两个在同一格,就只需要加一次
        int dp[][][]=new int [N*2+2][N+1][N+1];
        for(int k=2;k<=N+N;k++){
    
    
            for(int i1=1;i1<=N;i1++){
    
    
                for(int i2=1;i2<=N;i2++){
    
    
                    int j1=k-i1;
                    int j2=k-i2;
                    //看是否符合要求
                    if(j1>=1&&j1<=N&&j2>=1&&j2<=N){
    
    
                        int t=arr[i1][j1];
                        if(i1!=i2)t+=arr[i2][j2];
                        int temp=dp[k][i1][i2];
                        temp=Math.max(temp,dp[k-1][i1-1][i2-1]+t);//上上
                        temp=Math.max(temp,dp[k-1][i1-1][i2]+t);  //下右、
                        temp=Math.max(temp,dp[k-1][i1][i2-1]+t);  //右下
                        temp=Math.max(temp,dp[k-1][i1][i2]+t);    //右右
                        
                        dp[k][i1][i2]=temp;

                    }
                }
            }


        }
        System.out.println(dp[N+N][N][N]);

    }
}

Guess you like

Origin blog.csdn.net/qq_44844588/article/details/108219071