题目链接: 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; }
思考: 思考能力, 代码能力有待提高。