题目背景
作为学习刻苦、成绩优秀的回报,妈妈决定开始每个星期给杀马特一点零花钱。
题目描述
作为创造产奶纪录的回报,Farmer John决定开始每个星期给Bessie一点零花钱。
FJ有一些硬币,一共有N (1 <= N <= 20)种不同的面额。每一个面额都能整除所有比它大的面额。
他想用给定的硬币的集合,每个星期至少给Bessie某个零花钱的数目C (1 <= C <= 100000000)。请帮他计算他最多能支付多少个星期的零花钱。
输入输出格式
输入格式:
第1行: 两个由空格隔开的整数: N 和 C;
第2到第N+1行: 每一行有两个整数表示一个面额的硬币:硬币面额V (1 <= V <= 100,000,000)拥有的该面额的硬币数B (1 <= B <= 1,000,000)。
(感谢fyszzhouzj,现错误已改正)
输出格式:
第1行: 一个单独的整数,表示最多能给支付多少个星期至少为C的零用钱。
输入输出样例
输入样例#1:
3 6
10 1
1 100
5 120
输出样例#1:
111
说明
【样例说明】
杀马特的妈妈想要每个星期给杀马特六美分。他有100个1美分硬币,120个5美分硬币,和一个10美分硬币。他妈妈可以在一个星期超额付给杀马特一个10美分硬币,然后接下来的10个星期每星期付给杀马特两个5美分硬币。最后100个星期每星期付给杀马特一个1美分硬币跟一个5美分硬币。
【10.12】考试T1
自以为打了个极为正确的贪心然而gg。
数组开成了20000000,原来好像是想开成2000000 ,n明明<=20.。。。。。。。倒也无妨,要命的是多开了一个没用的数组。。。
。。。
QWQ 天让蒟蒻爆零,蒟蒻不得不爆零。
附考试代码:
改掉数组后,只过了四个点。
当时的思路是:边读入边判断,遇到>=c的面额整个直接加入答案,< c的放到数组里存起来,最后将数组从小到大排个序。先选入一个最大的,按住大的不动,再从最小的开始加。没有考虑到答案有可能是数组中最大值的倍数之类的情况。
比如这样:
c=13
处理后的数组:
5 5 5 3 3 2 2 1 1 1
此时的最优解应当是先选入两个5,再从3开始加。这样“花的冤枉钱最少”
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2000000+2;
int a[maxn],b[maxn];
int n,c,v,x,sum;
int main()
{
//freopen("money.in","r",stdin);
//freopen("money.out","w",stdout);
int l=0;
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++)//n种面额
{
scanf("%d%d",&v,&x);//v:面额 x:该面额的硬币数
if(v>=c) sum+=x;
else if(v<c)
{
for(int k=l+1;k<=l+x;k++) a[k]=v;
l+=x;
}
}
sort(a+1,a+l+1);
int r=l,s=0;
for(int i=1;i<=l;i++)
{
if(a[i]+a[r]>=c&&r>i)
{
sum++;
r--;
s=0;
}
else if(r>i)
{
s+=a[i];
if(s+a[r]>=c)
{
sum++;
r--;
s=0;
}
}
}
printf("%d\n",sum);
//fclose(stdin);
//fclose(stdout);
return 0;
}
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=20+2;
int n,c,sum;
struct node
{
int x,v;
}a[maxn];
bool cmp(node a,node b)
{
return a.v>b.v;
}
int main()
{
int cnt=0;
int w,x;
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&w,&x);
if(w>=c) sum+=x;
else if(w<c)
{
a[++cnt].v=w;
a[cnt].x=x;
}
}
sort(a+1,a+cnt+1,cmp);
while(1)
{
int s=c;
for(int i=1;i<=cnt;i++)
{
if(a[i].v<=s&&a[i].x>0)
{
int t=min(s/a[i].v,a[i].x);
s-=t*a[i].v;
a[i].x-=t;
}
}
if(s>0)
{
for(int i=cnt;i>=1;i--)//从小的开始加
{
if(s<=a[i].v&&a[i].x>0)
{
s=0;
a[i].x--;
break;
}
}
}
if(s>0) break;
sum++;
}
printf("%d\n",sum);
return 0;
}