2.10

[P2340 USACO03FALL] Cow Exhibition G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)\

  • 很不错的一道题,我们考虑把本题转换为01背包,因为每只奶牛只有选或者不选两种可能性
  • \(dp[i][j]\)记录为在前i头奶牛中,智商为j时所得到的情商最大数
  • 根据01背包,我们只需要枚举i,j即可,也就是奶牛种数和智商的的容量
  • 因为存在负数,所以设定中间值400000,可以理解为之前的开端0向右平移了400000个单位
import java.io.*;
import java.util.*;

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 final int N = 410;
    static final int SUMIQ = (int) 8e5;
    static milk[] milks = new milk[N];
    static int n;
    static int[] dp = new int[SUMIQ + 10];

    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 {
//        return cin.next();
//    }




    @Override
    public void run() {
        try {
            n = nextInt();
            for (int i = 1; i <= n; i++) {
                milks[i] = new milk();
                int iq = nextInt();int eq = nextInt();
                milks[i].iq = iq; milks[i].eq = eq;
            }
            Arrays.fill(dp, -0x3f3f3f3f);
            dp[400000] = 0;
            for (int i = 1; i <= n; i++) {
                if (milks[i].iq > 0) {
                    for (int j = SUMIQ; j >= milks[i].iq; j--) {
                        dp[j] = Math.max(dp[j], dp[j - milks[i].iq] + milks[i].eq);
                    }
                } else {
                    for (int j = 1; j <= SUMIQ + milks[i].iq; j++) {
                        dp[j] = Math.max(dp[j], dp[j - milks[i].iq] + milks[i].eq);
                    }
                }
            }
            int ans = 0;
            for (int i = 400000; i <= SUMIQ; i++) {
                if (dp[i] >= 0) {
                    ans = Math.max(ans, dp[i] + i - 400000);
                }
            }
            cout.println(ans);
            cout.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    static class milk {
        int iq;
        int eq;
    }
}

[P1541 NOIP 2010 提高组] 乌龟棋 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 设数组\(dp[num1][num2][num3][num4]\)为打出卡牌1,卡牌2,卡牌3,卡牌4时所得到的最高分数
  • 在设置一个\(score[j]\)数组来存储每个格子的分数即可
import java.io.*;
import java.util.*;

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 final int N = 400;
    static int[] score = new int[N];
    static int[] cardNum = new int[5];
    static int n, m;
    static int[][][][] dp = new int[45][45][45][45];
    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 {
//        return cin.next();
//    }




    @Override
    public void run() {
        try {
            n = nextInt();m = nextInt();
            for (int i = 1; i <= n; i++) {
                score[i] = nextInt();
            }

            for (int i = 1; i <= m; i++) {
                int x = nextInt();
                cardNum[x]++;
            }

            dp[0][0][0][0] = score[1];
            for (int i = 1; i <= 4; i++) {
                for (int num1 = 0; num1 <= cardNum[i]; num1++) {
                    for (int num2 = 0; num2 <= cardNum[i]; num2++) {
                        for (int num3 = 0; num3 <= cardNum[i]; num3++) {
                            for (int num4 = 0; num4 <= cardNum[i]; num4++) {
                                int bushu = num1 + num2 * 2 + num3 * 3 + num4 * 4 + 1;
                                if (num1 != 0) dp[num1][num2][num3][num4] = Math.max(dp[num1][num2][num3][num4], dp[num1 - 1][num2][num3][num4] + score[bushu]);
                                if (num2 != 0) dp[num1][num2][num3][num4] = Math.max(dp[num1][num2][num3][num4], dp[num1][num2 - 1][num3][num4] + score[bushu]);
                                if (num3 != 0) dp[num1][num2][num3][num4] = Math.max(dp[num1][num2][num3][num4], dp[num1][num2][num3 - 1][num4] + score[bushu]);
                                if (num4 != 0) dp[num1][num2][num3][num4] = Math.max(dp[num1][num2][num3][num4], dp[num1][num2][num3][num4 - 1] + score[bushu]);
                            }
                        }
                    }
                }
            }

            cout.println(dp[cardNum[1]][cardNum[2]][cardNum[3]][cardNum[4]]);
            cout.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

P4310 绝世好题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 暴力的解法是设置\(dp[i]\)前i个数中最长子序列,转换成了最长上升子序列问题。得了90分,寻找正确解
  • 考虑到只要我们两个数的同一位同为1,那么就符合\(a[i]\&a[j]=1\)条件,那么我们可以在枚举每一个数时,去枚举这个数的每一位,可以用这个写法((1 << j) & x),记得最后更新一下即可
import java.io.*;
import java.util.*;

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;
    static final int N = (int) (1e5 + 10);
    static long[] a = new long[N];
    static int[] dp = new int[32];


    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 {
//        return cin.next();
//    }




    @Override
    public void run() {
        try {
            n = nextInt();
            for (int i = 1; i <= n; i++) {
                int x = nextInt();
                int max = 0;
                for (int j = 0; j <= 31; j++) {
                    if(((1 << j) & x) != 0) {
                        max = Math.max(max, dp[j] + 1);
                    }
                }

                for (int j = 0; j <= 31; j++) {
                    if(((1 << j) & x) != 0) {
                        dp[j] = Math.max(dp[j], max);
                    }
                }
            }

            int ans = 0;
            for (int i = 0; i <= 31; i++) {
                ans = Math.max(ans, dp[i]);
            }
            cout.println(ans);
            cout.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

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