链接:点击打开链接
题意:现有n种钱币,给出每种钱币的大小和数量,并且大面额的一定是小面额的倍数,现在每周要发c个单位的工资,问最多可以发几周
代码:
#include <queue>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
struct node{
int u,v;
friend bool operator<(node a,node b){
return a.u>b.u;
}
}s[105];
int use[105];
int main(){ //这个题的关键在于,面额大的一定是面额小的倍数
int n,c,i,j,id,tt,ans,tmp; //因此大于c的直接发,剩下的从大到小尽可能的不超
while(scanf("%d%d",&n,&c)!=EOF){ //过c,再从小到大取一张使得超过c的最小
for(i=1;i<=n;i++) //这样取得原因在于如果从小往大取,则一定可以变成
scanf("%d%d",&s[i].u,&s[i].v); //一张更大的金额,因此从大到小取,使得,每次的浪
id=-1,ans=0; //费最小
sort(s+1,s+n+1);
for(i=1;i<=n;i++){
if(s[i].u>=c){
ans+=s[i].v;
s[i].v=0;
}
else{
id=i;
break;
}
}
if(id==-1){
printf("%d\n",ans);
continue;
}
while(1){
tt=c;
memset(use,0,sizeof(use));
for(i=id;i<=n;i++){
tmp=min(s[i].v,tt/s[i].u);
use[i]=tmp;
tt-=tmp*s[i].u;
if(tt<=0)
break;
}
if(tt>0){
for(i=n;i>=id;i--){
if(s[i].v>0&&tt<=s[i].u){
use[i]++;
tt-=s[i].u;
break;
}
}
}
if(tt>0)
break;
tt=INF;
for(i=1;i<=n;i++)
if(use[i])
tt=min(tt,s[i].v/use[i]);
ans+=tt;
for(i=id;i<=n;i++)
if(use[i])
s[i].v-=tt*use[i];
}
printf("%d\n",ans);
}
return 0;
}