1. 程式人生 > >[Usaco2007 Dec]寶石手鐲

[Usaco2007 Dec]寶石手鐲

.com www. read 博客 輸入 ++ right 輸入格式 題目

題目描述

貝茜在珠寶店閑逛時,買到了一個中意的手鐲。很自然地,她想從她收集的 N(1 <= N <= 3,402)塊寶石中選出最好的那些鑲在手鐲上。對於第i塊寶石,它的重量為W_i(1 <= W_i <= 400),並且貝茜知道它在鑲上手鐲後能為自己增加的魅力值D_i(1 <= D_i <= 100)。由於貝茜只能忍受重量不超過M(1 <= M <= 12,880)的手鐲,她可能無法把所有喜歡的寶石都鑲上。 於是貝茜找到了你,告訴了你她所有寶石的屬性以及她能忍受的重量,希望你能幫她計算一下,按照最合理的方案鑲嵌寶石的話,她的魅力值最多能增加多少。

輸入格式

第1行: 2個用空格隔開的整數:N 和 M

第2..N+1行: 第i+1行為2個用空格隔開的整數:W_i、D_i,分別為第i塊寶石 的重量與能為貝茜增加的魅力值

輸出格式

第1行: 輸出1個整數,表示按照鑲嵌要求,貝茜最多能增加的魅力值


01背包的裸題。設dp[i]為使用了i個單位容量時的最大魅力值,c[i]為第i個物品的重量,v[i]為第i個物品的魅力值。那麽:

\[ dp[j]= \left\{\begin{array}{rcl} max(dp[j],dp[j-c[i]])+v[i])&j>=c[i]\ dp[j]&j<c[i] \end{array}\right. \]

如果你不知道這個轉移方程怎麽來的,而且你要學01背包......你可以看博主的這篇博客:

淺談01背包

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 3501
#define maxm 15001
using namespace std;
 
int dp[maxm],c[maxn],v[maxn];
int n,m;
 
inline int read(){
    register int x(0),f(1); register char c(getchar());
    while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
    while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
 
int main(){
    n=read(),m=read();
    for(register int i=1;i<=n;i++) c[i]=read(),v[i]=read();
    for(register int i=1;i<=n;i++){
        for(register int j=m;j>=c[i];j--){
            if(dp[j-c[i]]+v[i]>dp[j]) dp[j]=dp[j-c[i]]+v[i];
        }
    }
    printf("%d\n",dp[m]);
    return 0;
}

時間復雜度為:

\[ O(NM) \]

[Usaco2007 Dec]寶石手鐲