题目大意: Igor 深深爱上了Tanya. 现在, Igor想表达他的爱意, 他便在Tanya家对面的墙上写下一串数字. Igor认为, 数字越大, Tanya接受他的机会就越大(Ps:恋爱中的人智商为负). 不幸的是, 他只有v升油漆, 每个数字都会花掉一定的油漆(ai:数i花掉的油漆). Igor不喜欢0所以数中不会出现0(1..9). 问Igor能得到的最大的数是多少.
思路: 刚看完题目时以为是个背包, 然后去寻找状态去了(找啊找, 找啊找), 额又智障了...
跳出了背包这个思路以后. 仔细想了想, 怎么让这个数最大.
1. 位数---毫无疑问位数越多数越大, 所以我们每次操作都不能使位数减少.
2. 在这个基础上我们想要每次操作的数尽可能的大.
咦, 那尝试一下贪心···
伪代码:
WHILE (V is valid)
找出满足条件一的所有数
选择其中最大的并更新V
代码实现:
利用优先队列来求出最大数(注意, 使用优先队列前因将其清空)
数字可能很大, 于是用字符串处理
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
int v, t, min_cost = 100001;
int ans[10], cost[10];
char out[10000000];
priority_queue<int> que;
int cnt = 0;
int main()
{
scanf("%d", &v);
for ( int i = 0; i < 9; i ++ )
{
scanf("%d", cost + i);
min_cost = min(min_cost, cost[i]);
}
while ( v > 0 )
{
t = v / min_cost;
if ( t == 0 ) break;
while ( !que.empty() ) que.pop();
for ( int i = 0; i < 9; i ++ )
if ( ( v - cost[i] ) / min_cost == t - 1 && v >= cost[i] )
que.push(i);
if ( !que.empty() )
{
t = que.top();
ans[t] ++;
v -= cost[t];
}
}
for ( int i = 8; i >= 0; i -- ) while ( ans[i] -- ) out[cnt++] = '1' + i;
if ( cnt == 0 ) printf("-1\n");
else
{
out[cnt] = '\0';
printf("%s\n", out);
}
return 0;
}