1. 程式人生 > >藍橋杯-開心的金明-01揹包-java

藍橋杯-開心的金明-01揹包-java

問題描述   金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間他自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說:“你的房間需要購買哪些物品,怎 麼佈置,你說了算,只要不超過N元錢就行”。今天一早金明就開始做預算,但是他想買的東西太多了,肯定會超過媽媽限定的N元。於是,他把每件物品規定了一 個重要度,分為5等:用整數1~5表示,第5等最重要。他還從因特網上查到了每件物品的價格(都是整數元)。他希望在不超過N元(可以等於N元)的前提 下,使每件物品的價格與重要度的乘積的總和最大。
  設第j件物品的價格為v[j],重要度為w[j],共選中了k件物品,編號依次為 j1,j2,……,jk,則所求的總和為:
  v[j1]*w[j1]+v[j2]*w[j2]+ …+v[jk]*w[jk]。(其中*為乘號)
  請 你幫助金明設計一個滿足要求的購物單。 輸入格式   輸入檔案 的第1行,為兩個正整數,用一個空格隔開:
  N m
  (其中N(<30000)表示總錢 數,m(<25)為希望購買物品的個數。)
  從第2行到第m+1行,第j行給出了編號為j-1的物品的基本資料,每行有2個非負整數
  v p
  (其中v表示該物品的價格(v<=10000),p表示該物品的重要度(1~5)) 輸出格式   輸出檔案只有一個正整數,為不超過總錢數的物品的價格與重要度乘積的總和的最大值(<100000000)。 樣例輸入 1000 5
800 2
400 5
300 5
400 3
200 2 樣例輸出 3900 資料規模和約定 解題思路: 標準的01揹包問題                     動態轉移方程 : dp【錢】 = max(dp【錢-花費】 + 花費*重要度,dp【錢】)                    注意的地方 第二層迴圈要從n開始 就是從後往推                    為什麼呢 ? 01揹包問題 就是每個物品只有兩個狀態 拿還是不拿                    並且給你一個上限 這個上限說不能超過多少錢或者不超過多大的空間 都是一樣的                    所以在限制條件下你不清楚 這個如果拿了這個東西會產生什麼樣的影響 所以你要列舉每一種情況                    列舉 那就是迴圈 那從哪列舉呢? 從n開始 如果從前開始推得話 東西你會拿重 求得的解 會比最優解大                    假設 物品a  20元  你從前面列舉  按照演算法 當限制是20元時 拿物品a 合適  一直加加 當限制到40元時 演算法認為還是拿物品a合適 所以又拿了一遍物品a 求的解是大了                    但是不符合題目要求 所以 這麼寫不對  解釋的很囉嗦 網上01揹包的詳解 很多 大家可以搜搜 程式碼: package 演算法訓練;

import java.util.Scanner;

public class 開心的金明 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            int n = scanner.nextInt();
            int m = scanner.nextInt();
            int [][] arr = new int [2][m];
            for (int i = 0; i < m; i++) {
                arr[0][i] = scanner.nextInt();
                arr[1][i] = scanner.nextInt();
            }
            int [] dp = new int [n+1];
            for (int i = 0; i < m; i++) {
                for (int j = n; j >= arr[0][i]; j--) {
                    int v = dp[j - arr[0][i]] + arr[0][i] * arr[1][i];
                    dp[j] = dp[j] > v ? dp[j] : v;
                }
            }
            System.out.println(dp[n]);
        }
    }

}