题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=791
转载自:http://www.cnblogs.com/windysai/p/3432414.html
Color the fence
- 描述
-
Tom has fallen in love with Mary. Now Tom wants to show his love and write a number on the fence opposite to
Mary’s house. Tom thinks that the larger the numbers is, the more chance to win Mary’s heart he has.
Unfortunately, Tom could only get V liters paint. He did the math and concluded that digit i requires ai liters paint.
Besides,Tom heard that Mary doesn’t like zero.That’s why Tom won’t use them in his number.
Help Tom find the maximum number he can write on the fence.
- 输入
- There are multiple test cases.
Each case the first line contains a nonnegative integer V(0≤V≤10^6).
The second line contains nine positive integers a1,a2,……,a9(1≤ai≤10^5). - 输出
- Printf the maximum number Tom can write on the fence. If he has too little paint for any digit, print -1.
- 样例输入
-
5 5 4 3 2 1 2 3 4 5 2 9 11 1 12 5 8 9 10 6
- 样例输出
-
55555 33
题目意思:给定v升的颜料和9个需要花费ad 升的颜料,花费ad 升的颜料意味着得到第d个数字,现在要求在所有的花费不超过v升的情况下,使得这些数字组合起来是最大的。
一开始直接从最小花费的颜料着手,如果花费的颜料是相同的,就转到从d(也就是位数)最大贪心。这样测试9就开始卡住了。
受到乌冬兄的指点迷津,终于有了思路,陆陆续续改了很多次,终于过了。以下摘自他的语录,白话文,大家请谅解:
稳用颜料最少,最大的数字,先保证位数最长,然后再将剩余颜料从大数字开始贪心
因为要数最大,所以根据“数”的比较顺序:
1。比较位数
2。从高位开始比较从数字比较的方法,推出贪心既思路
由于本人悟性太低,下面是更详细的解说:
1、先稳到用最小颜料既数字d,假设它价值为c
2、先构造出s = v div c个d,求出剩余颜料r = v mod c
3、从最高位扫描s,从大到小枚举可替换数字d' >= d,假设价值为c':若c'-c <= r,则替换当前位置的d为d', r -= c' - c
4、最后得出替换后的s, s'即为所求
注意:价值即一个数字要使用的颜料量1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 8 const int maxn = 1e6 + 5; 9 struct paint 10 { 11 int index; // 数字 12 int num; // 该数字所花费的颜料量 13 } a[maxn], b[maxn]; 14 15 int s[maxn]; // 用于保存结果 16 17 int cmp(paint a, paint b) 18 { 19 if (a.num != b.num) // 先保证用的颜料量最少 20 return a.num < b.num; 21 return a.index > b.index; // 再保证数字最大 22 } 23 24 int main() 25 { 26 int i, j, v, tmp, t1; 27 while (scanf("%d", &v) != EOF) 28 { 29 // freopen("in.txt", "r", stdin); 30 for (i = 1; i <= 9; i++) 31 { 32 a[i].index = i; 33 scanf("%d", &a[i].num); 34 b[i].index = i; //b用于保存未排序前的序列,以便下面从大数字开始枚举 35 b[i].num = a[i].num; 36 } 37 sort(a+1, a+10, cmp); 38 if (v < a[1].num) // v比最少花费的颜料更少 39 printf("-1 "); 40 else 41 { 42 tmp = v / a[1].num; // 得出最大位数 43 if (v % a[1].num == 0) // 如果刚好可以除尽,最大的数就是tmp个a[1].num的数。 44 { 45 for (i = 0; i < tmp; i++) 46 printf("%d", a[1].index); 47 printf(" "); 48 } 49 else 50 { 51 for (i = 0; i < tmp; i++) 52 { 53 s[i] = a[1].index; // 先得出目前来说最长的数字,但可能不是最终结果 54 } 55 int r = v % a[1].num; // 余数 56 t1 = r; 57 for (i = 0; i < tmp; i++) 58 { 59 for (j = 9; j >= 1; j--) // 从最大的位数开始枚举 60 { 61 if (b[j].num - a[1].num <= r && a[1].index < b[j].index) // 没有超过余数且数字比原来的排列数字的位数要大 62 { 63 s[i] = b[j].index; 64 r = r - (b[j].num - a[1].num); // 余数要有所减少 65 break; 66 } 67 } 68 } 69 if (t1 == r) // 如果根本没有可替换的数,那么就和刚好除尽的是同一种情况 70 { 71 for (i = 0; i < tmp; i++) 72 printf("%d", a[1].index); 73 printf(" "); 74 } 75 else 76 { 77 for (i = 0; i < tmp; i++) // 否则有替换的就输出新的最大数字 78 { 79 printf("%d", s[i]); 80 } 81 printf(" "); 82 } 83 } 84 } 85 } 86 return 0; 87 }