2.9

2.9

[P1435 IOI 2000] 回文字串 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 先说思路,我们这里有样例Ab3bd,反着读是db3bA,我们发现重复的是b3b,不重复的是Ad两个字符,相当于我们只要补全这两个字符为偶数,就可以使他成为回文串。答案就为2。
  • ok,那么就把问题转移成了简单的两个子串求最长子序列的问题。
import java.io.*;
import java.util.Scanner;

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 Scanner cin = new Scanner(System.in);
    static final int N = (int) (1e3 + 10);
    static long[][] dp = new long[N][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;
//    }
//
//    public static String next() throws IOException {
//        cin.nextToken();
//        return cin.sval;
//    }



    @Override
    public void run() {

            String s1 = cin.next();
            String s2 = new StringBuffer(s1).reverse().toString();

            for (int i = 1; i <= s1.length(); i++) {
                for (int j = 1; j <= s2.length(); j++) {
                    if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                        dp[i][j] = dp[i - 1][j - 1] + 1;
                    } else {
                        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                    }
                }
            }

            cout.println(s1.length() - dp[s1.length()][s2.length()]);
            cout.flush();

    }


}

P1854 花店橱窗布置 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 状态数组\(dp[i][j]\)表达的意义为,前i多花要插入前j个花瓶可以得到的最大美学值。
  • 由于我们的顺序是定死了的,则我们在枚举花瓶j时,必须要控制其转换方程是由\((1,j-1)\)这个区间转换而来的。
  • 那么转移方程为\(dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + color[i][j])\)
  • 注意我们这个方程\(dp[i][j]\),表达意思中前j个花瓶(默认第i多花放在花瓶j中)
  • 我们只需要枚举\((f, v)\)找到最大的美学值,然后找到是上一行哪一个值迭代出来的就行了
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;

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) (1e2 + 10);
    static long[][] dp = new long[N][N];
    static int f, v;
    static int[][] arr = new int[N][N];
    static int[][] fangXiang = new int[N][N];
    static int[] pp = new int[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;
    }

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



    @Override
    public void run() {
        try {
            f=nextInt();v=nextInt();
            for (int i = 1; i <= f; i++) {
                for (int j = 1; j <= v; j++) {
                    arr[i][j] = nextInt();
                }
            }

            for (int i = 1; i <= f; i++) {
                Arrays.fill(dp[i], -0x3f3f3f3f);
            }
            for (int i = 1; i <= f; i++) {
                for (int j = 1; j <= v; j++) {
                    for (int k = 1; k <= j; k++) {
                        if (dp[i - 1][j - k] + arr[i][j] > dp[i][j]) {
                            dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k] + arr[i][j]);
                            fangXiang[i][j] = j - k;
                        }
                    }
                }
            }

            int l = 0;
            long ans = -0x3f3f3f3f;
            int startX = 0, startY = 0;
            for (int i = f; i <= v; i++) {
                if (dp[f][i] > ans) {
                    ans = Math.max(ans, dp[f][i]);
                    startX = f; startY = i;
                }
            }
            cout.println(ans);
            pp[++l] = startY;
            for (int i = 1; i < f; i++) {
                startY = fangXiang[startX][startY];
                startX--;
                pp[++l] = startY;
            }

            for (int i = f; i >= 1; i--) {
                cout.print(pp[i] + " ");
            }
            cout.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

P1833 樱花 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 首先本题是一个组合背包问题(完全背包+多重背包+01背包)
  • 所以我们要先知道这几个背包咋做
  • 01背包:每一个物品只能买一次
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;

public class Main implements Runnable {

//    static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static Scanner cin = new Scanner(System.in);
    static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    static int n, v;
    static final int N = 1010;
    static bag[] bags = new bag[N];
    static int[][] dp = new int[N][N];
    
    public static void main(String[] args) {
        new Thread(null, new Main(), "", 1 << 29).start();
    }

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

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




    @Override
    public void run() {
        try {
           n = nextInt(); v = nextInt;
           for(int i = 1; i <= n; i++) {
               bags[i] = new bag();
               int val = nextInt();
               int weight = nextInt();
               bags[i].val = val;bags[i].weight = weight;
           }
           
           for(int i = 1; i <= n; i++) {
               for(int j = 1; j <= v; j++) {
                   if(j < bags[i].weight) {
                       dp[i][j] = dp[i - 1][j];
                   } else {
                       dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - bags[i].weight] + bags[i].val)
                   }
               }
           }
           
           cout.println(dp[n][v]);
           cout.flush;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    static class bag {
        int val;
        int weight;
    }
}
  • 完全背包:每一个物品可以买很多次
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;

public class Main implements Runnable {

//    static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static Scanner cin = new Scanner(System.in);
    static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    static int n, v;
    static final int N = 1010;
    static bag[] bags = new bag[N];
    static int[][] dp = new int[N][N];
    
    public static void main(String[] args) {
        new Thread(null, new Main(), "", 1 << 29).start();
    }

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

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




    @Override
    public void run() {
        try {
           n = nextInt(); v = nextInt();
           for(int i = 1; i <= n; i++) {
               bags[i] = new bag();
               int val = nextInt();
               int weight = nextInt();
               bags[i].val = val;bags[i].weight = weight;
           }
           
           for(int i = 1; i <= n; i++) {
               for(int j = 1; j <= v; j++) {
                   if(j < bags[i].val) {
                       dp[i][j] = dp[i - 1][j];
                   } else {
                       dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - bags[i].val] + bags[i].weight);
                   }
               }
           }
           
           cout.println(dp[n][v]);
           cout.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    static class bag {
        int val;
        int weight;
    }
}
  • 多重背包(每个物品可以取有限次),可以理解成把多重背包拆解成01背包,有三种方法,其一种每个多重背包化解成拆分成单个01背包复杂度为\(O(n*\sum cnt)\),其二运用2进制优化拆分成01背包\(O(n * log (cnt))\),还有优先队列(有点小难)可以优化到\(O(n * m)\)
  • 朴素版
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;

public class Main implements Runnable {

    //    static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static Scanner cin = new Scanner(System.in);
    static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    static int n, v;
    static final int M = (int) (1e4 + 10);
    static bag[] bags = new bag[M];
    static int[] dp = new int[M];

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

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

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




    @Override
    public void run() {
        try {
            n = nextInt(); v = nextInt();
            int num = 0;
            for(int i = 1; i <= n; i++) {
                int weight = nextInt();
                int val = nextInt();
                int cnt = nextInt();
                for(int j = 1; j <= cnt; j++) {
                    bags[++num] = new bag();
                    bags[num].val = val;bags[num].weight = weight;
                }
            }
            //cout.println(num);
            for(int i = 1; i <= num; i++) {
                for(int j = v; j >= bags[i].weight; j--) {
                    if(j < bags[i].weight) {
                        dp[j] = dp[j];
                    } else {
                        dp[j] = Math.max(dp[j], dp[j - bags[i].weight] + bags[i].val);
                    }
                }
            }
            cout.println(dp[v]);
            cout.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    static class bag {
        int val;
        int weight;
    }
}
  • 2进制优化版
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;

public class Main implements Runnable {

    //    static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static Scanner cin = new Scanner(System.in);
    static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    static int n, v;
    static final int M = (int) (2e4 + 10);
    static bag[] bags = new bag[M];
    static int[] dp = new int[M];

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

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

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




    @Override
    public void run() {
        try {
            n = nextInt(); v = nextInt();
            int num = 0;
            for(int i = 1; i <= n; i++) {
                int weight = nextInt();
                int val = nextInt();
                int cnt = nextInt();
                int k = 1;
                while(k <= cnt) {
                    bags[++num] = new bag();
                    bags[num].val = val * k; bags[num].weight = weight * k;
                    cnt -= k;
                    k *= 2;
                }

                if(cnt != 0) {
                    bags[++num] = new bag();
                    bags[num].val = val * cnt; bags[num].weight = weight * cnt;
                }
            }
            //cout.println(num);
            for(int i = 1; i <= num; i++) {
                for(int j = v; j >= bags[i].weight; j--) {
                    if(j < bags[i].weight) {
                        dp[j] = dp[j];
                    } else {
                        dp[j] = Math.max(dp[j], dp[j - bags[i].weight] + bags[i].val);
                    }
                }
            }
            cout.println(dp[v]);
            cout.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    static class bag {
        int val;
        int weight;
    }
}
  • ok,所以组合背包其实就是01背包和完全背包的结合体,问题解决
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;

public class Main implements Runnable {

    //    static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static Scanner cin = new Scanner(System.in);
    static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    static int n, hs, ms, he, me;
    static final int N = (int) (1e3 + 10);
    static final int M = (int) (1e5 + 10);

    static bag[] bags = new bag[M];
    static long[] dp = new long[N];

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

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

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




    @Override
    public void run() {
        try {
            String begin = next(); String end = next();n = nextInt();
            String[] split = begin.split(":");
            String[] split1 = end.split(":");
            hs = Integer.parseInt(split[0]); ms = Integer.parseInt(split[1]);
            he = Integer.parseInt(split1[0]); me = Integer.parseInt(split1[1]);
            int totalTime = 0;
            if (me < ms) {
                he--;me += 60;
            }
            totalTime = (he - hs) * 60 + (me - ms);//容量
            int num = 0;
            for(int i = 1; i <= n; i++) {
                int time = nextInt();int color = nextInt();int p = nextInt();
                if (p == 0) {
                    bags[++num] = new bag();
                    bags[num].time = time; bags[num].color = color;bags[num].blog = 1;
                } else {
                    int k = 1;
                    while(k <= p) {
                        bags[++num] = new bag();
                        bags[num].time = time * k; bags[num].color = color * k;bags[num].blog = 0;
                        p -= k;
                        k *= 2;
                    }

                    if (p != 0) {
                        bags[++num] = new bag();
                        bags[num].time = time * p; bags[num].color = color * p;bags[num].blog = 0;
                    }
                }
            }

            for (int i = 1; i <= num; i++) {
                if (bags[i].blog == 0) {
                    for (int j = totalTime; j >= bags[i].time; j--) {
                        dp[j] = Math.max(dp[j], dp[j - bags[i].time] + bags[i].color);
                    }
                } else {
                    for (int j = bags[i].time; j <= totalTime; j++) {
                        dp[j] = Math.max(dp[j], dp[j - bags[i].time] + bags[i].color);
                    }
                }
            }

            cout.println(dp[totalTime]);
            cout.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    static class bag {
        int time;
        int color;
        int blog;//0 为01背包 1 为完全背包
    }
}
  • 板子题练习

2. 01背包问题 - AcWing题库

3. 完全背包问题 - AcWing题库

4. 多重背包问题 I - AcWing题库

5. 多重背包问题 II - AcWing题库

6. 多重背包问题 III - AcWing题库

7. 混合背包问题 - AcWing题库

posted @ 2025-02-09 23:20  Mikkeykarl  阅读(22)  评论(0)    收藏  举报