HDU 5527 Too rich 贪心 + DFS

  题目链接: https://vjudge.net/contest/162184#problem/A

  题目描述: 给出一个整数 p , 给出1, 5, 10, 20, 50, 100, 200, 500, 1000, 2000 的数量, 要求用最多的数拼成 p 。

  解题思路: 贪心, 要凑出最多的数量必须让面值越大的数数量越少, 所以sum[i]记录从 0 ~ i 手中持有的价值总,  所以我们先假设将更小面值的纸币全部用掉, 然后判断剩下要凑的钱数和

        当前的面值的关系。 有个小trick 。 以后自己想。解释不明白

  题目代码: 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;
int v[15] = {0, 1, 5, 10, 20, 50, 100, 200, 500, 1000, 2000};
int n[15];
ll ans;
ll sum[15];
//int flag;

void dfs( ll rest, int pos, ll num ) {
//    if( flag == 1 ) return;
    if( rest < 0 ) return;
    if( pos == 0 ) {
        if( rest == 0 ) {
            if( ans < num ) {
                ans = num;
//                cout << rest << " " << pos << " " << num << endl;
            }
        }
        return;
    }
    ll temp = (ll)rest - sum[pos-1]; // 将更小面值的纸币全部用掉
    if( temp < 0 ) temp = 0;
    ll tn = temp / (ll)v[pos];
    if( temp % (ll)v[pos] ) tn++; // 不够
    if( tn <= n[pos] ) dfs( rest-tn*v[pos], pos-1, num+tn );
//    else {
//        flag = 1;
//        return;
//    }
    tn++;
    if( tn <= n[pos] ) dfs( rest-tn*v[pos], pos-1, num+tn );
    return;
}
int main() {
    int t;
    scanf( "%d", &t );
    while( t-- ) {
        int p;
        scanf( "%d", &p );
        ans = -1;
//        flag = 0;
        memset( n, 0, sizeof( n ) );
        for( int i = 1; i <= 10; i++ ) {
            scanf( "%d", &n[i] );
        }
        for( int i = 1; i <= 10; i++ ) {
            sum[i] = sum[i-1] + v[i] * n[i];
        }
        dfs( p, 10, 0 );
//        if( flag == 1 ) {
//            printf( "-1\n" );
//        }
//        else {
//            printf( "%lld\n", ans );
//        }
        printf( "%lld\n", ans );
    }
    return 0;
}
View Code

  思考: 思考能力, 代码能力有待提高。 

posted on 2017-05-03 22:26  FriskyPuppy  阅读(171)  评论(0编辑  收藏  举报

导航