Zuo Shen Promoción avanzada Clase 5 (intento codicioso, modelo de intento a distancia)

Tabla de contenido

[Caso 1 Intento codicioso]

[Descripción del Título]

[Análisis de ideas]

【Código】

[Caso 2: Modelo de prueba dentro del alcance]

[Descripción del Título]

[Análisis de ideas]

【Código】

[Caso 3: Modelo de prueba dentro del alcance]

[Descripción del Título]

[Análisis de ideas]

【Código】

[Caso 4 Modelo probado de izquierda a arriba + Modelo probado en rango]

[Descripción del Título]

[Análisis de ideas]

【Código】

[Caso 5: Modelo de prueba dentro del alcance]

[Descripción del Título] 

[Análisis de ideas]

【Código】


Si cree que puede escribir bien, puede unirse al grupo QQ 907575059 para discutir el conocimiento de los algoritmos.

[Caso 1 Intento codicioso]

[Descripción del Título]

[Análisis de ideas]

Primero ordene toda la matriz, si el valor de la última posición es mayor que el límite, se devuelve Integer.MAX_VALUE, lo que indica que es imposible cruzar la orilla.

arr[arr.length - 1] <= límite / 2 Si se cumple esta condición, dos personas cualesquiera pueden formar parejas en un barco
arr[0] > límite / 2 Si se cumple esta condición, sólo una persona puede subir al mismo bote

De lo contrario, busque la posición más a la derecha que sea menor o igual a límite / 2 y luego use dos punteros, p para atravesar de izquierda a 0 y q para atravesar de izquierda + 1 a arr.lenth.

(1) Si p + q <= límite, entonces q++ (cuando q++ aquí, cuente la longitud del recorrido de q) hasta p+q>límite. En este momento, todas las longitudes correspondientes en el lado izquierdo de p satisfacen el límite p + q < correspondiente. Si el lado izquierdo de p no es lo suficientemente largo, se usará todo p para resolver q.

(2) Si p+q > límite, p--.

Una vez completado el recorrido, cada persona que queda a la derecha organiza un barco separado, y las personas restantes a la izquierda organizan (leftNum + 1)/2; organiza tantos barcos como el número de q resueltos.

【Código】

package AdvancedPromotion5;

import java.util.Arrays;

/**
 * @ProjectName: study3
 * @FileName: Ex1
 * @author:HWJ
 * @Data: 2023/9/24 16:18
 */
public class Ex1 {
    public static void main(String[] args) {
        int[] arr = {1,2,2,3,4,4,5,5,5,6,6,6,6,7,7,7,8,8,8,9,9,9,11,10,11,12};
        System.out.println(need(arr, 13));
    }

    public static int need(int[] arr, int limit) {
        Arrays.sort(arr);
        if (arr[arr.length - 1] > limit) {
            return Integer.MAX_VALUE;
        }

        if (arr[arr.length - 1] <= limit / 2) { // 如果满足这个条件,任意两个人都可以配对上一个船
            return (arr.length + 1) / 2;
        }
        if (arr[0] > limit / 2) {  // 如果满足这个条件,只能一个人上一个穿
            return arr.length;
        }

        int left = -1;
        for (int i = arr.length - 1; i >= 0; i--) {
            if (arr[i] <= limit / 2) {
                left = i;
                break;
            }
        }

        int p = left;
        int q = left + 1;
        int unSolved = 0;
        while (p >= 0) {
            int solve = 0;
            while (q < arr.length && arr[p] + arr[q] <= limit) {
                solve++;
                q++;
            }
            if (solve > 0) {
                p = Math.max(p - solve, -1); // 如果能解决完,就全部解决
                // 不能就直接赋值-1,退出循环。
            } else {
                unSolved++;
                p--;
                // 我们只用记录左边没有解决的数量,就可以通过左边总数得到左边已经解决的数量
                // 左边解决的数量,又等于右边解决的数量,通过这个又可以得到右边没有解决的数量。这样就得到了我们所需要的所有信息
            }
        }
        int leftNum = left + 1;
        int right = arr.length - leftNum;
        return right + (unSolved + 1) / 2;
    }
}

[Caso 2: Modelo de prueba dentro del alcance]

[Descripción del Título]

[Análisis de ideas]

Para conocer el método para encontrar subsecuencias comunes, consulte el Caso 6 Zuoshen Advanced Class 4 (problema del juego Nim, sistema pseudo-ario k, recursividad a programación dinámica, rutinas recursivas de combinación de prioridades, rutinas recursivas de subsecuencias, recursividad de subsecuencias Rutinas, técnicas de compresión de programación dinámica) Blog_Studying~-blog CSDN

El primer método consiste en encontrar la subsecuencia común más larga de la cadena str y su unStr inverso, que es su subsecuencia palíndromo más larga.

El segundo enfoque consiste en dar una definición dp[i][j] para representar str[i. . . La longitud de la subsecuencia palíndromo más larga en j].

Entonces las posibilidades de la subsecuencia palíndromo más larga incluyen:

(1) Contiene la posición i, incluye la posición j, solo str[i] == str[j]

(2) Incluye posición i pero no incluye posición j

(3) No incluye la posición i, pero incluye la posición j

(4) No incluye la posición i y no incluye la posición j.

【Código】

package AdvancedPromotion5;


/**
 * @ProjectName: study3
 * @FileName: Ex2
 * @author:HWJ
 * @Data: 2023/9/24 16:59
 */
public class Ex2 {
    public static void main(String[] args) {
        String str = "123akmk321";
        System.out.println(getMax(str));
    }

    public static int getMax(String s){
        char[] str = s.toCharArray();
        int[][] map = new int[str.length][str.length];

        for (int i = 0; i < str.length; i++) { // 填充i == j 和 j == i + 1的情况,这个是很好的判断,不用考虑可能性
            map[i][i] = 1;
            if (i < str.length - 1){
                map[i][i + 1] = str[i] ==  str[i + 1] ? 2 : 1;
            }
        }
        for (int i = str.length - 3; i >= 0; i--) {
            for (int j = i + 2; j < str.length; j++) {
                int p1 = map[i][j - 1];
                int p2 = map[i + 1][j];
                int p3 = map[i + 1][j - 1] + (str[i] == str[j] ? 2 : 0);
                map[i][j] = Math.max(p1, Math.max(p2, p3));
            }
        }
        return map[0][str.length - 1];
    }
}

[Caso 3: Modelo de prueba dentro del alcance]

[Descripción del Título]

[Análisis de ideas]

El resultado de la construcción dp[i][j] indica el número mínimo de caracteres adicionales necesarios para convertir str[i....j] en una cadena palíndromo.

(1) str [i]! = str [j], hay dos estrategias en este momento: primero obtenga str [i...j-1] para convertirlo en una cadena palíndromo y luego convierta la segunda cadena palíndromo Agregar una cadena [j] en el lado izquierdo de la cuerda hará que toda la cuerda sea un palíndromo. O primero arregle str[i +1...j] para convertirla en una cadena palíndromo, y luego agregue una str[i] al lado derecho de la segunda cadena palíndromo, y el conjunto será una cadena palíndromo.

(2) str [i] == str [j], en este momento solo str [i + 1 ... j-1] necesita convertirse en una cadena palíndromo, y el conjunto es una cadena palíndromo.

Minimizar las últimas tres posibilidades nos dará la respuesta que necesitamos. Después de completar la tabla mediante programación dinámica, obtenemos la respuesta invirtiendo la tabla.

【Código】

package AdvancedPromotion5;

/**
 * @ProjectName: study3
 * @FileName: Ex3
 * @author:HWJ
 * @Data: 2023/9/24 17:10
 */
public class Ex3 {
    public static void main(String[] args) {
        String s = "123afga1321";
        System.out.println(record(s));
    }

    public static String record(String s) {
        int[][] map = recordMap(s);
        String ans = recordStr(map, s.toCharArray());
        return ans;
    }

    public static int[][] recordMap(String s) {
        char[] str = s.toCharArray();
        int len = str.length;
        int[][] map = new int[len][len];
        for (int i = 0; i < len; i++) {
            map[i][i] = 0;
            if (i < len - 1) {
                map[i][i + 1] = (str[i] == str[i + 1] ? 0 : 1);
            }
        }
        for (int i = len - 3; i >= 0; i--) {
            for (int j = i + 2; j < len; j++) {
                int p1 = map[i + 1][j] + 1;
                int p2 = map[i][j - 1] + 1;
                map[i][j] = Math.min(p1, p2);
                if (str[i] == str[j]) {
                    map[i][j] = Math.min(map[i][j], map[i + 1][j - 1]);
                }
            }
        }
        return map;
    }

    public static String recordStr(int[][] map, char[] str) {
        int len = map.length;
        int need = map[0][len - 1];
        int p = 0;
        int q = len - 1;
        char[] ans = new char[len + need];
        int i = 0;
        int j = ans.length - 1;
        while (p <= q) {
            if (p == q) {
                ans[i] = str[p];
                break;
            }
            if (str[p] == str[q]) {
                int p1 = map[p + 1][q - 1];
                int p2 = map[p + 1][q];
                if (map[p][q] == p1) {
                    ans[i++] = str[p++];
                    ans[j--] = str[q--];
                } else if (map[p][q] == p2 + 1) {
                    ans[i++] = str[p];
                    ans[j--] = str[p++];
                } else {
                    ans[i++] = str[q];
                    ans[j--] = str[q--];
                }
            } else {
                int p1 = map[p + 1][q];
                if (map[p][q] == p1 + 1) {
                    ans[i++] = str[p];
                    ans[j--] = str[p++];
                } else {
                    ans[i++] = str[q];
                    ans[j--] = str[q--];
                }
            }
        }
        return String.valueOf(ans);
    }
}

[Caso 4 Modelo probado de izquierda a arriba + Modelo probado en rango]

[Descripción del Título]

[Análisis de ideas]

Debido a que queremos cortarlos todos en el número mínimo de cortes de subcadenas palíndromos, podemos atravesar cada posibilidad de izquierda a derecha. Al atravesar las posibilidades, juzgaremos si el corte actual es razonable. Si se garantiza que el corte actual será una subcadena palíndromo razonable, es decir, brochetas, continúa reduciéndose. La complejidad temporal de este tipo de recorrido es O (N ^ 2), y debido a que cada recorrido requiere un proceso de juicio, la complejidad temporal del juicio es O (N), por lo que la complejidad temporal general es O (N ^ 3). En este momento, la complejidad del tiempo es demasiado alta y necesitamos acelerar el proceso de juicio a través de una variedad de modelos.

Para contar una tabla, map[i][j] indica si str[i....j] es una subcadena palíndromo. La subcadena palíndromo debe satisfacer str[i] == str[j] y str[i + 1 ][j - 1] también es una subcadena palíndromo.

【Código】

package AdvancedPromotion5;

/**
 * @ProjectName: study3
 * @FileName: Ex4
 * @author:HWJ
 * @Data: 2023/9/25 8:32
 */
public class Ex4 {
    public static void main(String[] args) {
        String str = "ABA";
        boolean[][] map = judge(str);
        System.out.println(getMin(str.toCharArray(), 0, map));
    }

    public static int getMin(char[] str, int index, boolean[][] map){
        if (index == str.length){
            return -1;
        }
        int res = Integer.MAX_VALUE;
        for (int i = index; i < str.length; i++) {
            if (map[index][i]){
                res = Math.min(res, 1 + getMin(str, i + 1, map));
            }
        }
        return res;

    }

    public static boolean[][] judge(String s){
        boolean[][] map = new boolean[s.length()][s.length()];
        char[] str = s.toCharArray();
        for (int k = 0; k < str.length; k++) {
            map[k][k] = true;
            if (k < str.length - 1){
                map[k][k + 1] = str[k] == str[k + 1];
            }
        }
        for (int k = str.length - 3; k >= 0 ; k--) {
            for (int l = k + 2; l < str.length; l++) {
                if (str[k] == str[l]){
                    map[k][l] = map[k + 1][l - 1];
                }else {
                    map[k][l] = false;
                }
            }
        }
        return map;
    }
}

[Caso 5: Modelo de prueba dentro del alcance]

[Descripción del Título] 

[Análisis de ideas]

Construya una tabla bidimensional, map[i][j] representa cuántas subsecuencias palindrómicas tiene str[i...j].

Luego la subsecuencia palíndromo se divide en las siguientes posibilidades:

(1) Contiene la posición i e incluye la posición j.

(2) Incluye la posición i pero no incluye la posición j.

(3) No incluye la posición i, pero incluye la posición j.

(4) No incluye la posición i y no incluye la posición j.

map [i + 1] [j] representa el número de todas las subsecuencias de palíndromo que no contienen la posición i, que pueden contener o no la posición j, lo que representa la posibilidad de (3) (4). j

map[i][j - 1] representa el número de todas las subsecuencias de palíndromo que no contienen la posición j, que pueden contener o no la posición i, lo que representa las posibilidades de (2) (4).

map [i + 1] [j-1] representa el número de todas las subsecuencias de palíndromos que no contienen la posición j y no contienen la posición j, lo que representa la posibilidad de (4).

(1) La posibilidad solo es posible cuando str[i] == str[j], y el valor es igual a map[i+1][j-1] + 1. Porque si estos dos se eliminan, es un número palíndromo, además sigue siendo un número palíndromo, y hay un caso más en el que solo existen estas dos secuencias.

【Código】

package AdvancedPromotion5;

/**
 * @ProjectName: study3
 * @FileName: Ex5
 * @author:HWJ
 * @Data: 2023/9/25 9:05
 */
public class Ex5 {
    public static void main(String[] args) {
        String str= "ABA";
        System.out.println(getNum(str));
    }

    public static int getNum(String s){
        char[] str = s.toCharArray();
        int len = str.length;
        int[][] map = new int[len][len];
        for (int i = 0; i < len; i++) {
            map[i][i] = 1;
            if (i < len - 1){
                map[i][i + 1] = (str[i] == str[i + 1] ? 3 : 2);
            }
        }
        for (int i = len - 3; i >= 0; i--) {
            for (int j = i + 2; j < len; j++) {
                map[i][j] = map[i + 1][j] + map[i][j - 1] - map[i + 1][j - 1];
                if (str[i] == str[j]){
                    map[i][j] += (map[i + 1][j - 1] + 1);
                }
            }
        }
        return map[0][len - 1];
    }
}

Supongo que te gusta

Origin blog.csdn.net/weixin_73936404/article/details/133232169
Recomendado
Clasificación