2.8

2.8

[P1004 NOIP 2000 提高组] 方格取数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 这道题一开始是想用\(dp[i][j]\)来代表走到i,j后所得到的最大值,根据转移方程\(dp[i][j] = max(dp[i][j - 1],dp[i - 1][j]) + a[i][j]\)然后通过记录方向的方法,回溯回去把路径上的值赋值为0。
  • 但是结果是有问题的,这种方法本质上感觉是一种贪心,我们陷入了局部最优,我们只是保证了每一次路径是最大值,并没有保证两个路径之和是最大值。
  • 改变之后决定更换dp状态,\(dp[i][j][k][t]\),表示走到第一次走到i,j,和第二次走到k,t得到的最大值。ok那么转移方程跟着更新即可,\(dp[i][j][k][t] = max(dp[i][j - 1][k][t - 1],dp[i - 1][j][k - 1][t], dp[i][j - 1][k - 1][t], dp[i - 1][j][k][t - 1]) + a[i][j] + a[k][t]\),当然当两点重合时,要减去一个,因为我们同一个点加了两次。
import java.io.*;
import java.util.*;

public class Main implements Runnable {

    static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    static int n;
    static final int N = 10;
    static long[][] g = new long[N][N];
    static long[][][][] dp = new long[N][N][N][N];//dp[i][j] 走到i,j时所得到的最大值
    static int[][] fangXiang = new int[N][N];
    // 1为you,2为xia,3为youxia

    public static void main(String[] args) {
        new Thread(null, new Main(), "", 1 << 29).start();
    }

    public static int nextInt() throws IOException {
        cin.nextToken();
        return (int) cin.nval;
    }



    @Override
    public void run() {
        try {
            n = nextInt();
            int x = nextInt(), y = nextInt();long val = nextInt();
            while(x != 0 && y != 0 && val != 0) {
                g[x][y] = val;
                x = nextInt(); y = nextInt(); val = nextInt();
            }

            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    for (int k = 1; k <= n; k++) {
                        for (int z = 1; z <= n; z++) {
                            dp[i][j][k][z] = Math.max(Math.max(dp[i - 1][j][k - 1][z], dp[i][j - 1][k - 1][z]),
                                                    Math.max(dp[i][j - 1][k][z - 1], dp[i - 1][j][k][z - 1])) + g[i][j] + g[k][z];
                            if (i == k && j == z) {
                                dp[i][j][k][z] -= g[i][j];
                            }
                        }
                    }
                }
            }

            cout.println(dp[n][n][n][n]);
            cout.flush();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}

[P1091 NOIP 2004 提高组] 合唱队形 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 很简单,其实就是求最大上升子序列,我们正着求一次,反着求一次,再枚举每一个点(记得减1),只要两者和最大,那么剔除的人就最少
import java.io.*;
import java.util.*;

public class Main implements Runnable {

    static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    static int n;
    static final int N = 110;
    static long[] t = new long[N];
    static long[] dpl_r = new long[N];
    static long[] dpr_l = new long[N];


    public static void main(String[] args) {
        new Thread(null, new Main(), "", 1 << 29).start();
    }

    public static int nextInt() throws IOException {
        cin.nextToken();
        return (int) cin.nval;
    }



    @Override
    public void run() {
        try {
            n = nextInt();
            for (int i = 1; i <= n; i++) t[i] = nextInt();
            Arrays.fill(dpl_r, 1);Arrays.fill(dpr_l, 1);

            for (int i = 1; i <= n; i++) {
                for (int j = i - 1; j >= 1; j--) {
                    if (t[j] < t[i]) {
                        dpl_r[i] = Math.max(dpl_r[j] + 1, dpl_r[i]);
                    }
                }
            }

            for (int i = n; i >= 1; i--) {
                for (int j = i + 1; j <= n; j++) {
                    if (t[j] < t[i]) {
                        dpr_l[i] = Math.max(dpr_l[j] + 1, dpr_l[i]);
                    }
                }
            }

            long cnt = 0;
            for (int i = 1; i <= n; i++) {
                cnt = Math.max(dpl_r[i] + dpr_l[i] - 1, cnt);
            }

            long ans = n - cnt;
            cout.println(ans);
            cout.flush();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}

[P2679 NOIP 2015 提高组] 子串 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 本题确实对我来说有点太难了,选用的这个题解的方法,没看得好懂,照着其转移方程码的代码,,,,感兴趣的去看原作者吧。。。

题解 P2679 【子串】 - 洛谷专栏 (luogu.com.cn)

import java.io.*;

public class Main implements Runnable {

    static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    static final int N = (int) (1e3 + 10);
    static final int M = 210;
    static final int mod = 1000000007;
    static int[][][][] dp = new int[2][M][M][2];//dp[i,j,k,z] 表示以a串i位置结束时,b串j位置结束,所配对子串k,z选或不选
    static int n, m, k;

    public static void main(String[] args) {
        new Thread(null, new Main(), "", 1 << 29).start();
    }

    public static int nextInt() throws IOException {
        cin.nextToken();
        return (int) cin.nval;
    }

    public static String next() throws IOException {
        cin.nextToken();
        return cin.sval;
    }



    @Override
    public void run() {
        try {
            n = nextInt();m = nextInt();k = nextInt();
            String s1 = next(); String s2 = next();


            int val = 1;
            dp[0][0][0][0] = 1;dp[1][0][0][0] = 1;
            for(int i = 1; i <= n; i++, val ^= 1) {
                for (int j = 1; j <= m; j++) {
                    for(int t = 1; t <= k; t++) {
                        if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                            dp[val][j][t][0] = (dp[val^1][j][t][1] + dp[val^1][j][t][0]) % mod;
                            dp[val][j][t][1] = (((dp[val^1][j - 1][t - 1][1] + dp[val^1][j - 1][t - 1][0] ) % mod)
                                    + dp[val^1][j - 1][t][1]) % mod;
                        } else {
                            dp[val][j][t][0] = (dp[val^1][j][t][1] + dp[val^1][j][t][0]) % mod;
                            dp[val][j][t][1] = 0;
                        }
                    }
                }
            }

            cout.println((dp[n&1][m][k][1] + dp[n&1][m][k][0]) % mod);
            cout.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}
posted @ 2025-02-08 17:01  Mikkeykarl  阅读(21)  评论(0)    收藏  举报