kuangbin带你飞专题十二 基础DP java题解

kuangbin带你飞:起飞~

kuangbin带你飞专题十二 基础DP

  • 1. Max Sum Plus Plus
  • 2. Ignatius and the Princess IV
  • 3. Monkey and Banana
  • 5. Super Jumping! Jumping! Jumping!
  • 6. Piggy-Bank
  • 7. 免费馅饼
  • 8. Tickets
  • 9. 最少拦截系统
  • 10. FatMouse's Speed

1. Max Sum Plus Plus

原题链接:Max Sum Plus Plus
思路:题意为找出n个数中m个不相交子段的最大和
1.定义状态dp[i][j],意为前 j 个数中选出的 i 组数的最大和,若简单DP状态转移为
dp[i][j]=MAX{ dp[i][j-1],dp[i-1][k] }+num[j] (i-1 2.跟背包问题类似,dp[i][]只和dp[i-1][],dp[i][]有关。可以使用滚动数组优化:
dp当前状态 [j]=MAX{ dp当前状态 [j-1],dp上一状态 [k] }+num[j] (i-1 3.可以看出,最终只需要保存MAX{dp上一状态 [k]}即可。所以,用一个数组保存lastMax[j]就可以了,lastMax[j]表示不包括 j 的 j 之前的最大和
4.最终的状态转移方程就变为:
dp[j]=MAX{ dp[j-1],lastMax[j-1] }+num[j] (i-1

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;


public class Main {
    static int mLen = (int) 1e6 + 10;
    static int[] num = new int[mLen];
    static int[] dp = new int[mLen];
    static int[] lastMax = new int[mLen];
    static int inf = 1 << 30;
    static int n, m;

    public static void main(String[] args) {
        //1e6的数据,使用输入输出挂
        InputReader in = new InputReader();
        PrintWriter out = new PrintWriter(System.out);
        while (in.hasNext()) {
            n = in.nextInt();
            m = in.nextInt();
            for (int i = 1; i <= m; i++) {
                num[i] = in.nextInt();
            }

            //状态初始化
            Arrays.fill(dp, 0);
            Arrays.fill(lastMax, 0);
            int Max = -inf;

            for (int i = 1; i <= n; i++) {
                Max = -inf;
                for (int j = i; j <= m; j++) {
                    dp[j] = Math.max(dp[j - 1], lastMax[j - 1]) + num[j];
                    lastMax[j - 1] = Max;
                    Max = Math.max(Max, dp[j]);
                }
            }
            //利用缓存加速,比syso快的多
            out.println(Max);
        }
        //用了out记得要关闭
        out.close();
    }
}

class InputReader {
    BufferedReader bf;
    StringTokenizer st;

    InputReader() {
        bf = new BufferedReader(new InputStreamReader(System.in));
    }

    boolean hasNext() {
        while (st == null || !st.hasMoreElements()) {
            try {
                st = new StringTokenizer(bf.readLine());
            } catch (Exception e) {
                return false;
            }
        }
        return true;
    }

    String next() {
        if (hasNext()) {
            return st.nextToken();
        }
        return null;
    }

    int nextInt() {
        return Integer.parseInt(next());
    }
}

2. Ignatius and the Princess IV

原题链接:Ignatius and the Princess IV
思路:不知道哪里用到DP了。。。数据很水,直接快排输出num[n+1/2]都可以AC,复杂度O(nlogn)。为了达到练习目的,此处采用Boyer-Moore 投票算法,复杂度O(n)。

import java.util.Scanner;


public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNextInt()) {
            int n = sc.nextInt();
            int[] num = new int[n];
            for (int i = 0; i < n; i++) {
                num[i] = sc.nextInt();
            }
            int ans = 0, element = 0;
            for (int i = 0; i < n; i++) {
                if (ans == 0) {
                    element = num[i];
                }
                if (num[i] == element) {
                    ans += 1;
                } else {
                    ans -= 1;
                }
            }
            System.out.println(element);
        }
    }
}

3. Monkey and Banana

原题链接:Monkey and Banana
思路:把砖块先按长度排序,问题就转化为了求上升子序列的最大和。宽度用于比较,高为值。注意每块砖有6种放置方法与最后的输出格式即可。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

class brick implements Comparable<brick> {
    int x, y, h;
    int maxH;

    public brick(int x, int y, int h, int maxH) {
        this.x = x;
        this.y = y;
        this.h = h;
        this.maxH = maxH;
    }

    @Override
    public int compareTo(brick b2) {
        if (this.x == b2.x) {
            if (this.y == b2.y) {
                return 0;
            } else {
                return this.y > b2.y ? 1 : -1;
            }
        } else {
            return this.x > b2.x ? 1 : -1;
        }
    }
}

public class Main {
    static int count = 0;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        while (sc.hasNextInt()) {
            int n = sc.nextInt();
            count++;
            if (n == 0) {
                return;
            }
            ArrayList<brick> list = new ArrayList<>();
            for (int i = 0; i < n; i++) {
                int x = sc.nextInt();
                int y = sc.nextInt();
                int h = sc.nextInt();
                list.add(new brick(x, y, h, h));
                list.add(new brick(y, x, h, h));
                list.add(new brick(h, x, y, y));
                list.add(new brick(x, h, y, y));
                list.add(new brick(y, h, x, x));
                list.add(new brick(h, y, x, x));
            }
            Collections.sort(list);
            int res = 0;
            for (int i = 1; i < list.size(); i++) {
                for (int j = 0; j < i; j++) {
                    brick bi = list.get(i), bj = list.get(j);
                    if (bi.x > bj.x && bi.y > bj.y) {
                        bi.maxH = Math.max(bi.maxH, bj.maxH + bi.h);
                    }
                }
                res = Math.max(res, list.get(i).maxH);
            }
			//注意格式!!!最后还有一个空格!!!我PE了三回才发现
            System.out.printf("Case %d: maximum height = %d \n", count, res);
        }
    }
}

5. Super Jumping! Jumping! Jumping!

原题链接:Super Jumping! Jumping! Jumping!
思路:上升子序列最大和模板

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNextInt()) {
            int n = sc.nextInt();
            if (n == 0) {
                return;
            }
            int max = 0;
            int[] num = new int[n];
            int[] dp = new int[n];
            for (int i = 0; i < n; i++) {
                num[i] = sc.nextInt();
                dp[i] = num[i];
            }
            for (int i = 1; i < n; i++) {
                for (int j = 0; j < i; j++) {
                    if (num[i] > num[j]) {
                        dp[i] = Math.max(dp[i], dp[j] + num[i]);
                    }
                }
                max = Math.max(max, dp[i]);
            }
            System.out.println(max);
        }
    }

}

6. Piggy-Bank

原题链接:Piggy-Bank
解题思路:需要装满的完全背包的变体,求最小价值。

import java.util.Arrays;
import java.util.Scanner;


public class Main {

    static int N, E, F, n,p,w;
    static final int inf = 0x3f3f3f3f;
    static int[] dp = new int[(int) 1e4 + 10];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
        for (int i = 0; i < N; i++) {
            E = sc.nextInt();
            F = sc.nextInt();
            n = sc.nextInt();
            int temp = F - E;
            Arrays.fill(dp, inf);
            dp[0] = 0;
            for (int j = 1; j <= n; j++) {
               p=sc.nextInt();
               w=sc.nextInt();
                for (int k = w; k <=temp ; k++) {
                    dp[k]=Math.min(dp[k],dp[k-w]+p);
                }
            }

            if (dp[temp] != inf) {
                System.out.printf("The minimum amount of money in the piggy-bank is %d. \n", dp[temp]);
            } else {
                System.out.printf("This is impossible. \n");
            }
        }
    }

}



7. 免费馅饼

原题链接:免费馅饼
解题思路:数塔问题,倒着DP就可以了,可以将数据想成一个倒三角,最后的出口是唯一确定的,只要递归地获取上一层左中右位置的最大值即可
递推式:dp[i][j] = max(dp[i + 1][j - 1], dp[i + 1][j], dp[i + 1][j + 1]) + pie[i][j];

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;


public class Main {
    static int n, t, x;
    static final int maxN = (int) 1e5 + 5;
    static int[][] dp = new int[maxN][15];
    static int[][] pie = new int[maxN][15];

    public static void main(String[] args) {
        InputReader in = new InputReader();//快速读入

        while (in.hasNext()) {
            n = in.nextInt();
            if (n == 0) {
                return;
            }
            for (int i = 0; i < maxN; i++) {
                for (int j = 0; j < 15; j++) {
                    dp[i][j] = 0;
                    pie[i][j] = 0;
                }
            }
            int end = 0;
            for (int i = 0; i < n; i++) {
                x = in.nextInt() + 1;
                t = in.nextInt();
                pie[t][x] += 1;//方便处理0位置
                end = Math.max(end, t);
            }
            for (int i = end; i >= 0; i--) {
                for (int j = 1; j <= 11; j++) {
                    dp[i][j] = max(dp[i + 1][j - 1], dp[i + 1][j], dp[i + 1][j + 1]) + pie[i][j];
                }
            }
            System.out.println(dp[0][6]);
        }
    }

    private static int max(int a, int b, int c) {
        return Math.max(a, Math.max(b, c));
    }

}

class InputReader {
    BufferedReader bf;
    StringTokenizer st;

    InputReader() {
        bf = new BufferedReader(new InputStreamReader(System.in));
    }

    boolean hasNext() {
        while (st == null || !st.hasMoreElements()) {
            try {
                st = new StringTokenizer(bf.readLine());
            } catch (Exception e) {
                return false;
            }
        }
        return true;
    }

    String next() {
        if (hasNext()) {
            return st.nextToken();
        }
        return null;
    }

    int nextInt() {
        return Integer.parseInt(next());
    }
}

8. Tickets

原题链接:Tickets
解题思路:along存储每个人单独所需时间,together存储每个人和他前面一起所需时间。则到第i个人所需最少时间就是他自己买加上i-1人用的时间或者他和前一个人一起买,前i-2人用的时间。
递推式:dp[i]=MIN{dp[i-1]+along[i],dp[i-2]+together[i]}

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static int[] alone = new int[2020];
    static int[] together = new int[2020];
    static int[] dp = new int[2020];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        for (int t = 0; t < T; t++) {
            int k = sc.nextInt();
            for (int i = 1; i <= k; i++) {
                alone[i] = sc.nextInt();
            }
            for (int i = 2; i <= k; i++) {
                together[i] = sc.nextInt();
            }
            dp[1] = alone[1];
            dp[2] = Math.min(alone[1] + alone[2], together[2]);
            for (int i = 3; i <= k; i++) {
                dp[i] = Math.min(dp[i - 1] + alone[i], dp[i - 2] + together[i]);
            }
            int h = dp[k] / 3600 + 8;
            int m = dp[k] % 3600 / 60;
            int s = dp[k] % 60;
            //12点时am,pm都能过,可能是没有12点时的数据
            if (h > 12) {
                System.out.printf("%02d:%02d:%02d pm \n", h - 12, m, s);
            } else {
                System.out.printf("%02d:%02d:%02d am \n", h, m, s);
            }
        }
    }
}

9. 最少拦截系统

原题链接:最少拦截系统
解题思路:求最长上升子序列的长度,LIS模板题。注意是多组数据

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static int[] h = new int[1010];
    static int[] dp = new int[1010];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNextInt()) {
            int n = sc.nextInt();
            for (int i = 0; i < n; i++) {
                h[i] = sc.nextInt();
                dp[i] = 1;
            }

            int ans = 0;
            for (int i = 0; i < n; i++) {
                for (int j =i + 1; j < n; j++) {
                    if (h[j] > h[i]) {
                        dp[j] = Math.max(dp[i] + 1, dp[j]);
                    }
                    ans = Math.max(ans, dp[i]);
                }

            }
            System.out.println(ans);
        }
    }

}

10. FatMouse’s Speed

原题链接:FatMouse’s Speed
解题思路:先排序,就转化为求最长降/升序子序列,注意还要输出路径
不知道错在哪了,求指点

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;

class mouse implements Comparable<mouse> {
    int id, w, v;

    public mouse(int id, int w, int v) {
        this.id = id;
        this.w = w;
        this.v = v;
    }


    @Override
    public int compareTo(mouse m2) {
       if (this.w==m2.w){
           return this.v>m2.v?1:-1;
       }else {
           return this.w<m2.w?1:-1;
       }
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        ArrayList<mouse> nest=new ArrayList<>();
        int[] dp=new int[1010];
        Arrays.fill(dp,1);
        int index=0,w=0,v=0;
        while (sc.hasNextInt()){
            w=sc.nextInt();
            v=sc.nextInt();
            nest.add(new mouse(++index,w,v));
        }
        Collections.sort(nest);
        System.out.println(index);
        
        int res=0;
        mouse mi,mj;
        for (int i = 0; i < index; i++) {
            for (int j = i+1; j <index ; j++) {
                mi=nest.get(i);
                mj=nest.get(j);
                if (mi.w>mj.w&&mi.v<mj.v){
                    dp[j]=Math.max(dp[j],dp[i]+1);
                }
            }
            res=Math.max(res,dp[i]);
        }
        System.out.println(res);
        for (int i = index-1; i >=0 ; i--) {
            if (dp[i]==res){
                System.out.println(nest.get(i).id);
                res--;
            }
        }
    }
}

未完待续……

你可能感兴趣的:(#,kuangbin带你飞)