La red de Blue Bridge Cup accede al análisis de DP y métodos generales de Java Yan

Primero fuera del tema

Triángulo digital

Recoger cacahuetes

Peaje mínimo

Descripción del título :
Hay una cuadrícula N × N. Completamos números enteros positivos en algunos de los cuadrados y colocamos el número 0 en otros cuadrados. Como se muestra abajo:

Inserte la descripción de la imagen aquí

Alguien comienza desde A en la esquina superior izquierda de la figura y puede caminar hacia abajo o hacia la derecha hasta llegar al punto B en la esquina inferior derecha.

En el camino que camina, puede tomar el número en el cuadrado (el cuadrado después de tomarlo se convertirá en el número 0).

Esta persona ha caminado dos veces desde el punto A hasta el punto B. Intente encontrar dos de estos caminos para que la suma de los números obtenidos sea la mayor.

Formato de entrada

La primera línea es un número entero N, que representa un gráfico de cuadrícula N × N.
Cada fila siguiente tiene tres números enteros, el primero es el número de fila, el segundo es el número de columna y el tercero es el número colocado en la fila y columna.

Los números de fila y columna comienzan desde 1, y la fila "0 0 0" significa el final.

Formato de salida

Genere un número entero que represente la mayor suma obtenida en las dos rutas.

rango de datos

N≤10

Muestra de entrada:

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

Salida de muestra:

67

Ideas

Método general Dp tetradimensional

这个题要求的是走两遍,每次的最大值相加,选过的
方格值为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)有两种方法:要
 么从上往下走走到了,要门从左往右走走到了,这样两
 个人就有了“四种”状态,取这四种状态的最大值,就是
 最后的答案;
 

Código


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]);

    }
}

Análisis DP de Yan

El método del que siempre hablamos transforma un DP tetradimensional en un DP tridimensional, porque lo que buscamos es caminar dos veces y se puede considerar como dos personas caminando al mismo tiempo, y no se puede seleccionar la misma cuadrícula repetidamente, por lo que el resultado final de caminar al mismo tiempo y caminar por separado es lo mismo.

Tomando dos rutas al mismo tiempo, la suma de sus abscisas y ordenadas es la misma. Establecemos esta suma en K. 因此(i,j)就可以表示为(i,K-i)dp [K] [i1] [i2] 表示两个人从(1,1)分别走到(i1,K-i1)和(i2,K-i2)所有路径的最大值no es fácil de entender, así que ve a dos imágenes
De y curso de mejora total de algoritmos

Inserte la descripción de la imagen aquí
Entonces el código:

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]);

    }
}

Supongo que te gusta

Origin blog.csdn.net/qq_44844588/article/details/108219071
Recomendado
Clasificación