揹包問題

01揹包問題思想是將將總數進行拆分,拆分紅每塊錢(每一個重量基數)。ios

算法實現是將每一個物體抽象爲一行,每一列爲總數的細分,再分別從物體自己的價格(重量)到總數循環,每一次都進行f[i]=max{f[i],f[i-v[j]]+v[i]*w[i]}(f[i]爲每一格的最大收益,v[i]爲物體價格/重量,w[i]爲物體價值) 的比較,這樣執行完每一行均可以刷新這個價格(重量)區間的最大收益算法

  • 例題1 (01揹包問題)

P1060 開心的金明函數

#include<iostream>
#include<algorithm>
using namespace std;

int N, m;
int sum[30010];

struct thing
{
    int price;
    int grade;
}things[30];

void input();//輸入函數

int main()
{
    int i, j;
    input();
    for (i = 1; i <= m; i++)
        for (j =N ; j >=things[i].price; j--)//*從後往前,這樣就不是被本行的計算覆蓋
            sum[j] = max(sum[j], things[i].price*things[i].grade + sum[j - things[i].price]);//計算公式,將問題拆分紅每塊錢
    cout << sum[N];
    return 0;
}

void input()
{
    cin >> N >> m;
    int i;
    for (i = 1; i <= m; i++)
        cin >> things[i].price >> things[i].grade;
}
  • 例題2 (01揹包問題)

P1164 小A點菜spa

#include<iostream>
using namespace std;
  
const int N = 120;
  
int v[N], f[N];
  
int main()
{
    int n, m;
    int i, j;
    f[0] = 1;//當錢正好購買一個菜的時候狀況
    cin >> n >> m;
    for (i = 1; i <= n; i++)
        cin >> v[i];
    for (i = 1; i <= n; i++)
        for (j = m; j >= v[i]; j--)
            f[j] = f[j] + f[j - v[i]];//f[j]爲不買當前菜的狀況數,f[j-v[i]]爲買了當前菜用剩下的錢買其餘菜的狀況數
    cout << f[m];
    return 0;
  }
  • 例題3 (徹底揹包問題)

P1616 瘋狂的採藥code

#include<iostream>
  #include<algorithm>
  using namespace std;
  
  const int N = 10010;
  
  struct Med
  {
    int time, value;
  }med[N];
  
  int sum[100010];
  
  int main()
  {
    int T, M;
    int i, j;
    cin >> T >> M;
    for (i = 1; i <= M; i++)
        cin >> med[i].time >> med[i].value;
    for (i = 1; i <= M; i++)
        for (j = med[i].time; j <= T; j++)//只有這裏跟01揹包反過來,這樣能夠不斷更新每個狀態的最大價值,能夠作到一直取
            sum[j] = max( sum[j],med[i].value + sum[j - med[i].time] );
    cout << sum[T];
    return 0;
  }
相關文章
相關標籤/搜索