题意:有n种面额的硬币。且面值大的一定能被面值小的整除。现告诉你每种面值硬币的个数。和一个值c。每周支出的钱必须大于等于c。问钱最多能用多少周。
#include<stdio.h>
typedef struct //定义一个结构v表示coin的面额,而n表示v面额纸币的钱数。
{
int v;
int n;
}Coin;
Coin coin[25];
int min(int a,int b)
{
return a>b?b:a;
}
void qsort(int l,int r) //快速排序 (数据最大才25个,可以用其他排序方法)按面额从小到大
{
Coin temp;
int i,j;
if(l<r)
{
i=l;
j=r;
temp=coin[l];
while(i<j){
while(i<j&&coin[j].v>=temp.v)
j--;
if(i<j)
coin[i++]=coin[j];
while(i<j&&coin[i].v<temp.v)
i++;
if(i<j)
coin[j--]=coin[i];
}coin[i]=temp;
qsort(l,i-1);
qsort(i+1,r);
}
}
int main(void)
{
int N,C,i,amount=0,use[30],sum,num,ma;
scanf("%d%d",&N,&C);for(i=0;i<N;i++)
scanf("%d%d",&coin[i].v,&coin[i].n);
qsort(0,N-1);
for(i=N-1;i>=0;i--) //如果纸币面额大于C直接使用。
{
if(coin[i].v>=C)
{
amount+=coin[i].n;
coin[i].n=0;
}
else
break;
}
sum=C;
while(1)
{
sum=C;
// for(i=0;i<N;i++)
// printf("%d ",coin[i].n);
memset(use,0,sizeof(use));
for(i=N-1;i>=0;i--) //从面额大的开始,尽可能使总数接近sum,但是绝对不能超过sum
{
if(sum>0&&coin[i].n)
{
num=min(sum/coin[i].v,coin[i].n);
sum-=num*coin[i].v;use[i]=num;
}
}
if(sum>0) //从面额小的到大的,使面额达到总数,或者刚好超出。
{
for(i=0;i<N;i++)
{
if(sum>0&&coin[i].n)
{
num=min(coin[i].n-use[i],(sum+coin[i].v-1)/coin[i].v);
sum-=num*coin[i].v;
use[i]+=num;
}
}
}
if(sum>0)break; //经过上述的方法,sum还没到0或者负数,说明已经没办法了,程序结束
ma=1e9;
for(i=0;i<N;i++)
{
if(use[i])
{
ma=min(ma,coin[i].n/use[i]); //这次的对每种钱币选择最多可以执行ma次
}
}
amount+=ma; //这种情况直接当作执行了ma次
for(i=0;i<N;i++)
{
if(use[i])
{
coin[i].n-=ma*use[i];//使数量变成上述情况执行ma次之后剩余数量
}
}
}
printf("%d\n",amount);}
poj 3040 贪心
最新推荐文章于 2023-12-23 13:11:25 发布