poj3040试题 此题的思路还是能想到的 实现起来代码略长
我参考了他人的结题报告:https://blog.csdn.net/zwj1452267376/article/details/50429521
不废话 上代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define Max 30
using namespace std;
typedef struct money{
int value;
int number;
}m;
m coin[Max];
bool cmp(m a,m b)
{
return a.value>b.value;
}
int n,c;
int main()
{
int i,j,k;
scanf("%d %d",&n,&c);
//输入
for( i=0;i<n;i++)
{
scanf("%d %d",&coin[i].value,&coin[i].number);
}
//对面值大于等于c的 直接取走
int cnt=0;
sort(coin,coin+n,cmp);//按面值从大到小排序
for(i=0;i<n;i++){
if(coin[i].value>=c)
{
cnt+=coin[i].number;
coin[i].number=0;
}
}
//下面只是剩下面值小于c的了
int use[Max];//标记使用的大小
while(1){
memset(use,0,sizeof(use));
int mm=c;
//下面还是往大了挑
for(i=0;i<n;i++){
if(!coin[i].number) continue;//没有就算了
if(coin[i].number>0){
int k=mm/coin[i].value;
int mi=min(k,coin[i].number);
mm-=mi*coin[i].value;//第一轮挑选
coin[i].number=coin[i].number-mi;
if(mm<=0)
{
cnt++;
break;//挑选成功
}
}
}
if(mm>0)//必须挑选第二次//从小到大拿
{
for(i=n-1;i>=0;i--)
{
if(!coin[i].number) continue;
for(k=1;k<=coin[i].number;k++)
{
coin[i].number--;//硬币减1
mm-=k*coin[i].value;
if(mm<=0)
{
cnt++;
break;//够了 不用挑选了
}
}
if(mm<=0) break;
}
}
if(mm>0) break;//数轮挑选都失败了 只能跳出
}
printf("%d\n",cnt);
return 0;
}