1. 程式人生 > >hihoCoder184——滿減優惠

hihoCoder184——滿減優惠

題目1 : 滿減優惠

時間限制:10000ms 單點時限:1000ms 記憶體限制:256MB

描述

最近天氣炎熱,小Ho天天宅在家裡叫外賣。他常吃的一家餐館一共有N道菜品,價格分別是A1, A2, ... AN元。並且如果消費總計滿X元,還能享受優惠。小Ho是一個不薅羊毛不舒服斯基的人,他希望選擇若干道不同的菜品,使得總價在不低於X元的同時儘量低。

你能算出這一餐小Ho最少消費多少元嗎?

輸入

第一行包含兩個整數N和X,(1 <= N <= 20, 1 <= X <= 100)

第二行包含N個整數A1, A2, ..., AN。(1 <= Ai <= 100)

輸出

輸出最少的消費。如果小Ho把N道菜都買了還不能達到X元的優惠標準,輸出-1。

好久沒有寫題了,不得不說csdn這個編輯頁面真的是越改越差。

這道題我用了動規跟dfs做,結果dfs只有70分,我也不太懂,都po出來吧。動規好理解,就是01揹包問題,這裡再梳理一下這型別的問題。

大概意思就是:f [ I, j ] = max { ( f [ i-1, j - Wi ] + Pi)(其中 j >= Wi ) , f [ I-1, j ] } :f代表揹包裡有 I 個物體,其重量為 j 時的價值,其中每個物品的重量為Wi,價值為Pi。一般遍歷就是從 i : 0-->n,j :0 --> sum(Wi),(初始值都為零)也視情況而定。

int main(){
    int sum = 0;
    cin>>n>>x;
    int dp[200] = {0};
    
    for(int i = 0; i<n; i++){
        scanf("%d", &a[i]);
        sum += a[i];
    }
    
    int d = sum-x;
    if(d < 0) printf("-1\n");
    else if(d == 0) printf("%d\n", x);
    else{
        int out = -1;
        for(int i = 0; i<n; i++){
            for(int j = d; j>=0; j--){
                dp[j] = max(dp[j], dp[j-a[i]]+a[i]);
                out = max(dp[j], out);
            }
        }
        printf("%d", out);
    }
    return 0;
}

因為這個對物品的個數不敏感,所以不用dp[i,j],只用dp[i]即可。先將所有的物體全放進去,然後在物品總重大於x(d>0)的情況下能拿多少就拿多少。之前一直想著先動規出在總重小於x的時候拿到最大,然後再加上任意其他看最小,可行性很低,換個思路就簡單多了。

dfs我也不知道哪裡錯了,就是排列組合的說。

int a[200] = {0};
int n, x;

int dfs(int b, int sum){
    int out = 1000000000;
    if(sum >= x){
        return sum;
    }
    for(int i = b+1; i<n; i++){
        out = min(out, dfs(i, sum+a[i]));
    }
    return out;
}

int _main() {
    int sum = 0;
    int out = 1000000000;
    cin>>n>>x;
    
    for(int i = 0; i<n; i++){
        scanf("%d", &a[i]);
        sum += a[i];
    }
    
    if(sum < x){
        printf("-1\n");
        return 0;
    }
    sort(a, a+n, [](int x1, int x2){return x1 < x2;});
    
    for(int i = 0; i<n; i++){
        out = min(out, dfs(i, a[0]));
    }
    printf("%d\n", out);
    return 0;  
}