多重背包转为一维背包 POJ1276

传统思路如下

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

public class Main {
    public static void main(String[] args) throws Exception {
//        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        Scanner sc = new Scanner(System.in);
        StringTokenizer st;

        while (sc.hasNextInt()) {
//            while (br.ready()) {
//            st = new StringTokenizer(br.readLine());
//            int request = Integer.parseInt(st.nextToken()); // 取款机请求的现金
            int request = sc.nextInt(); // 取款机请求的现金
//            int N = Integer.parseInt(st.nextToken()); // 金额的种类
            int N = sc.nextInt(); // 金额的种类
            if(N == 0 && request == 0) break;
            int count[] = new int[N];
            int val[] = new int[N];

            for (int i = 0; i < N; i++) {
//                count[i] = Integer.parseInt(st.nextToken()); // 第i种类的金额个数
//                val[i] = Integer.parseInt(st.nextToken()); // 第i种类的金额面值
                count[i] = sc.nextInt(); // 第i种类的金额个数
                val[i] = sc.nextInt(); // 第i种类的金额面值
            }
            int[] dp = new int[request+1]; // 表示请求i金额最多输出得到实际金额
            int cnt[] = new int[request+1]; // i金额使用货币得到个数
            for (int i = 0; i < N; i++) { // 循环金额种类
                cnt = new int[request+1];
                for (int j = val[i]; j <= request; j++) { // 循环金额面值
                    if(dp[j] < dp[j - val[i]] + val[i] && cnt[j - val[i]] < count[i]) {
                        dp[j] = dp[j - val[i]] + val[i];
                        cnt[j] = cnt[j - val[i]] + 1;
                    }
                }
            }

            System.out.println(dp[request]);
        }
    }
}

 

posted @ 2021-04-22 14:32  姓蜀名黍  阅读(58)  评论(0)    收藏  举报