1. 程式人生 > >HDU 2546 飯卡(01揹包)

HDU 2546 飯卡(01揹包)

Description

電子科大本部食堂的飯卡有一種很詭異的設計,即在購買之前判斷餘額。如果購買一個商品之前,卡上的剩餘金額大於或等於5元,就一定可以購買成功(即使購買後卡上餘額為負),否則無法購買(即使金額足夠)。所以大家都希望儘量使卡上的餘額最少。
某天,食堂中有n種菜出售,每種菜可購買一次。已知每種菜的價格以及卡上的餘額,問最少可使卡上的餘額為多少。

Input

多組資料。對於每組資料:
第一行為正整數n,表示菜的數量。n<=1000。
第二行包括n個正整數,表示每種菜的價格。價格不超過50。
第三行包括一個正整數m,表示卡上的餘額。m<=1000。

n=0表示資料結束。

Output

對於每組輸入,輸出一行,包含一個整數,表示卡上可能的最小余額。

Sample Input

1 50 5 10 1 2 3 2 1 1 2 3 2 1 50 0

Sample Output

-45 32

解題報告:其實就是01揹包,最後要剩下大於等於5元但是接近5元的錢來買最貴的菜,揹包重量和價值是一樣的。

#include <stdio.h>
#include <string.h>
int value[1005], dp[1005];

int main()
{
   int n, m;
   while (scanf("%d", &n) != EOF && n){
        int maxValue = 0, id = -1;
        for (int i = 0; i < n; i ++){
            scanf("%d", value + i);
            if(maxValue < value[i]){
                maxValue = value[i];
                id = i;
            }
        }
        scanf("%d", &m);
        if(m < 5){
            printf("%d\n", m);
            continue;
        }
        memset(dp, 0, sizeof(dp));
        for (int i = 0; i < n; i ++){
            if(i == id) continue;
            for (int j = m - 5; j >= value[i]; j --){
                if(dp[j - value[i]] + value[i] > dp[j]){
                    dp[j] = dp[j - value[i]] + value[i];
                }
            }
        }
        printf("%d\n", m - dp[m-5] - maxValue);
   }
   return 0;
}

也可以排個序,來找最大值,但是揹包不需要有序,所以直接找最大值就可以了。