HDU1114——Piggy-Bank(裝滿的完全揹包)

題目鏈接

       這道題是一道完全揹包練手很好的題,比較容易,但是與純的完全揹包相比卻做了部分很巧的改動。其一,這是一個要求裝滿的完全揹包。其二,這個揹包求得並不是最大值,而是最小值。那麼如何解決這些變動呢?首先是看求最小值,這個好處理,那就是把max( )改成min( )就好了,但求最小值影響的卻不只是函數的變化,還影響了對裝滿揹包的處理。

       我們知道,無論是01揹包還是完全揹包,在求揹包最大價值時處理方式都是初始化時除dp[0]=0外,其他的dp[i]都初始化爲-∞。至於爲什麼這麼處理,很多博客都有解釋,大致是說這樣處理,非法狀況(即裝不滿的狀況)都會是負值,而只有裝滿的狀態纔是正值。因爲合法狀態下的max函數都把負數給篩去了(一個正數和一個負數求max,當然取正數咯),但是若用的是min,那就的不到正確結果了,這就是爲什麼此題求最小值會給初始化帶來影響,處理方式也很簡單,就是直接將-∞改爲+就好了,實現+就是給一個題目極端狀況下都達不到的最大值。那麼變動解決了,剩下的就是完全揹包的裸題了,採用一維數組處理,若dp[n]爲+時,就是裝不滿的情況輸出This is impossible.其他情況輸出最小值就ok了。這題還有個小坑,就是輸出末尾的句號。(表示少打了個點wrong了5遍很蛋疼。)


#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

typedef long long LL;
#define inf 1000000000

LL w[10005]={0};
LL v[10005]={0};
LL dp[10005];
int main()
{
    //freopen("in.in","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(w,0,sizeof(w));
        memset(v,0,sizeof(v));
        LL a, b;
        scanf("%lld%lld",&a,&b);
        LL W=b-a;
        dp[0]=0;
        for(int i=1;i<=W;i++)dp[i]=inf;
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld%lld",&v[i],&w[i]);
        for(int i=1;i<=n;i++)
            for(int j=w[i];j<=W;j++)
                dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
        if(dp[W]==inf)printf("This is impossible.\n");
        else printf("The minimum amount of money in the piggy-bank is %lld.\n",dp[W]);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章