1. 程式人生 > 其它 >揹包九講(9)

揹包九講(9)

揹包九講(9)

揹包問題求具體方案

有 N 件物品和一個容量是 V 的揹包。每件物品只能使用一次。

第 i 件物品的體積是 vi,價值是 wi。

求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。

輸出 字典序最小的方案。這裡的字典序是指:所選物品的編號所構成的序列。物品的編號範圍是 1…N

輸入格式

第一行兩個整數,N,V,用空格隔開,分別表示物品數量和揹包容積。

接下來有 N行,每行兩個整數 vi,wi,用空格隔開,分別表示第 ii 件物品的體積和價值。

輸出格式

輸出一行,包含若干個用空格隔開的整數,表示最優解中所選物品的編號序列,且該編號序列的字典序最小。

物品編號範圍是 1…N

資料範圍

0<N,V≤1000
0<vi,wi≤1000

輸入樣例

4 5
1 2
2 4
3 4
4 6

輸出樣例:

1 4

本題由於要去尋找字典序,即路徑,所以需要使用二維陣列來對每個物品進行記錄。

#include<iostream>
#include<algorithm>
const int N  = 1010;
using namespace std;
int n,m;
int f[N][N];
int v[N],w[N];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
    //倒著列舉物品 因為我們需要求出最小字典序,所以最後再去考慮第一個物品
    for(int i=n;i>=1;i--){
        for(int j=0;j<=m;j++){
            f[i][j]=f[i+1][j];
            if(j>=v[i]) f[i][j]=max(f[i][j],f[i+1][j-v[i]]+w[i]);
        }
    }
    int vol=m;
    for(int i=1;i<=n;i++){
        //需要求最小字典序 所以從第一個物品1開始列舉 能選一定要選 
        if(vol >= v[i] && f[i][vol] == f[i + 1][vol - v[i]] + w[i]){
            cout<<i<<' ';
            vol-=v[i];
        }
    }
    return 0;
}