思路:
贪心策略是使多发的面额最小(最优解)。分三个阶段:
- 首先面额不小于C的硬币属于没办法节约的类型,先统统发掉。
- 然后对硬币面额从大到小尽量凑得接近C,允许等于或不足C,但是不能超出C。
- 接着按硬币面额从小到大凑满C(凑满的意思是允许超出一个最小面值,ps此处的最小面值指的是硬币剩余量不为0的那些硬币中的最小面值),凑满之后得出了最优解,发掉,进入步骤2.
并没有很明白,也没有证出来~,只是有点感觉orz~~~
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,c;
struct node {
int v,b;
bool operator<(const node& n)const {
return v<n.v;
}
}no[33];
int main()
{
scanf("%d%d",&n,&c);
for(int i=0;i<n;i++)scanf("%d%d",&no[i].v,&no[i].b);
int sum=0;
sort(no,no+n);
n--;
while(n>=0&&no[n].v>=c){
sum+=no[n].b;
no[n].b=0;
n--;
}
while(true){
int t=0;
for(int i=n;i>=0;i--){
while(no[i].b>0&&t+no[i].v<=c){
t+=no[i].v;
no[i].b--;
}
}
for(int i=0;i<=n;i++){
while(no[i].b>0&&t<c){
t+=no[i].v;
no[i].b--;
}
if(t>=c){sum++;break;}
}
if(t<c)break;
}
printf("%d",sum);
return 0;
}