天天看點

小P的故事——神奇的Dota (完全背包問題)

完全背包問題

小P的故事——神奇的Dota

Problem Description

小P非常喜歡玩dota,不分晝夜的玩,結果他連做夢也都是裡面的畫面,一天晚上小P剛躺下就做了一個神奇的夢。。。

不死族的巫妖王發工資拉,死亡騎士拿到一張N元的鈔票(記住,隻有一張鈔票),為了防止自己在戰鬥中頻繁的死掉,他決定給自己買一些道具,于是他來到了地精商店前.

死亡騎士:“我要買道具!”

地精商人:“我們這裡有三種道具,血瓶150塊一個,魔法藥200塊一個,無敵藥水350塊一個.”

死亡騎士:“好的,給我一個血瓶.”

說完他掏出那張N元的大鈔遞給地精商人.

地精商人:“我忘了提醒你了,我們這裡沒有找客人錢的習慣的,多的錢我們都當小費收了的,嘿嘿.”

死亡騎士:"…"

死亡騎士想,與其把錢當小費送個他還不如自己多買一點道具,反正以後都要買的,早點買了放在家裡也好,但是要盡量少讓他賺小費.

現在死亡騎士感覺自己的智商不夠用是以希望小P幫他計算一下,最少他要給地精商人多少小費.但是小P的智商可是出了名的“不忍直視”啊,聰明非凡的你是以你能幫幫他嗎?

Input

輸入資料的第一行是一個整數T(1<=T<=100),代表測試資料的數量.然後是T行測試資料,每個測試資料隻包含一個正整數N(1<=N<=10000),N代表死亡騎士手中鈔票的面值.

注意:地精商店隻有題中描述的三種道具.

Output

對于每組測試資料,請你輸出死亡騎士最少要浪費多少錢給地精商人作為小費.

Sample Input

2

380

200

Sample Output

30

這是一道完全背包的問題,完全背包問題是指每種物品都有無限件,具體的解法我也不太了解,隻能先放代碼了:

#include <stdio.h>
#include <stdlib.h>

int max(int a, int b);

int main()
{
    int i,n,j,x,k,list;
    scanf("%d",&list);
    while ( list-- ) {
        scanf("%d",&x);
        // 令價值等于體積
        int p[4] = {0,150,200,350};
        int v[4] = {0,150,200,350};
        int B[100005] = {0};

        for ( j=1; j<=3; j++ ) {
            for ( k=1; k<=x; k++ ) {
                if ( p[j]<=k ) {
                    B[k] = max( B[k], B[k-p[j]] + v[j] );
                }
            }
        }

        printf("%d\n",x-B[x]);
    }

    return 0;
}

int max(int a, int b)
{
    if ( a>b ) {
        return a;
    }
    return b;
}

/***************************************************
User name: rj180323石旭
Result: Accepted
Take time: 8ms
Take Memory: 528KB
Submit time: 2019-01-24 14:40:22
****************************************************/