HDU - 5527 Too Rich 贪心

You are a rich person, and you think your wallet is too heavy and full now. So you want to give me some money by buying a lovely pusheen sticker which costs p dollars from me. To make your wallet lighter, you decide to pay exactly p dollars by as many coins and/or banknotes as possible.

For example, if p=17 and you have two 10 c o i n s , f o u r 5 coins, and eight 1 c o i n s , y o u w i l l p a y i t b y t w o 5 coins and seven $1
coins. But this task is incredibly hard since you are too rich and the sticker is too expensive and pusheen is too lovely, please write a program to calculate the best solution.
Input
The first line contains an integer T indicating the total number of test cases. Each test case is a line with 11 integers p,c1,c5,c10,c20,c50,c100,c200,c500,c1000,c2000, specifying the price of the pusheen sticker, and the number of coins and banknotes in each denomination. The number ci means how many coins/banknotes in denominations of i dollars in your wallet.

1≤T≤20000
0≤p≤109
0≤ci≤100000
Output
For each test case, please output the maximum number of coins and/or banknotes he can pay for exactly p dollars in a line. If you cannot pay for exactly p
dollars, please simply output ‘-1’.
Sample Input

3
17 8 4 2 0 0 0 0 0 0 0
100 99 0 0 0 0 0 0 0 0 0
2015 9 8 7 6 5 4 3 2 1 0

Sample Output

9
-1
36

逆向思维:从里面选取最少的达到sum-p。
由于前一个不一定是后一个的因子,所以要对每一位进行奇偶判断。
可以证明当前有500,500,500,200,200,200,2000,时,如果不选取2000,那么可以得到
2100,但是如果选取了2000,那么就不能得到2100了,至于为什么进行奇偶判断后就可行我也不太明白。

#include<bits/stdc++.h>
using namespace std;

int c[15];
int w[15];
int ret;

void dfs(int x,int now,int d){
    if(x == 0){
        if(now == 0) ret = min(ret,d);
        return;
    }
    int tmp = now/w[x];
    tmp = min(tmp,c[x]);
    if(x <= 10){
        dfs(x-1,now-tmp*w[x],d+tmp);
        if(tmp)
        dfs(x-1,now-tmp*w[x]+w[x],d+tmp-1);
    }
    else dfs(x-1,now-tmp*w[x],d+tmp);

}


int main(){
    int T;
    w[1] = 1;
    w[2] = 5;
    w[3] = 10;
    w[4] = 20;
    w[5] = 50;
    w[6] = 100;
    w[7] = 200;
    w[8] = 500;
    w[9] = 1000;
    w[10] = 2000;
    cin >> T;
    while(T--){
        ret = 1e9;
        int res = 0;
        int sum = 0;
        int m;
        scanf("%d",&m);
        for(int i = 1;i <= 10;i ++){
            scanf("%d",&c[i]);
            res += c[i];
            sum += c[i]*w[i];
        }
        if(sum < m){
            puts("-1");
        }
        else{
            dfs(10,sum-m,0);
            if(ret == 1e9) puts("-1");
            else printf("%d\n",res - ret);
        }

    }
    return 0;
}

补充:其实不用对每一位进行奇偶讨论,只需要对50和500进行奇偶讨论就行了。

#include<bits/stdc++.h>
using namespace std;

int c[15];
int w[15];
int ret;

void dfs(int x,int now,int d){
    if(x == 0){
        if(now == 0) ret = min(ret,d);
        return;
    }
    int tmp = min(now/w[x],c[x]);
    if(w[x] == 50 || w[x] == 500){
        if(tmp&1) tmp --;
        dfs(x-1,now-tmp*w[x],d+tmp);
    }
    else dfs(x-1,now-tmp*w[x],d+tmp);
}


int main(){
    int T;
    w[1] = 1;
    w[2] = 5;
    w[3] = 10;
    w[4] = 20;
    w[5] = 50;
    w[6] = 100;
    w[7] = 200;
    w[8] = 500;
    w[9] = 1000;
    w[10] = 2000;
    cin >> T;
    while(T--){
        ret = 1e9;
        int res = 0;
        int sum = 0;
        int m;
        scanf("%d",&m);
        for(int i = 1;i <= 10;i ++){
            scanf("%d",&c[i]);
            res += c[i];
            sum += c[i]*w[i];
        }
        if(sum < m){
            puts("-1");
        }
        else{
            dfs(10,sum-m,0);
            if(sum-m>=50&&c[5]) {c[5]--; dfs(10,sum-m-50,1);c[5]++;}
            if(sum-m>=500&&c[8]) {c[8]--; dfs(10,sum-m-500,1);c[8]++;}
            if(sum-m>=550&&c[5]&&c[8]) {c[5]--;c[8]--;dfs(10,sum-m-550,2);}
            if(ret == 1e9) puts("-1");
            else printf("%d\n",res - ret);
        }

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zstu_zy/article/details/81013417
今日推荐