Description
Windbreaker计划送一些项链给他的朋友们作为新年礼物。为了表示诚意,他决定自己制作全部的项链。他购买了若干种珍珠,每种珍珠都有特定的颜色。他要制作的项链都是M-完美的,也就是每条项链都是恰好由M种珍珠组成的。Windbreaker想知道他最多能送出多少条项链。给定每种珍珠的数目,你要回答的是Windbreaker最多可以制作多少条M-完美项链。
Input
输入包含多组测试数据。每组数据第一行是一个正整数n,代表有n种珍珠。第二行包含n个正整数,代表每种珍珠的数目。第三行包括1个正整数M,代表要制作的是M-完美项链。 输入数据以1行n=0结束。这组数据不用处理。
Output
对每组测试数据,输出一行答案,为一个整数,代表最多能制作的M-完美项链的数目。
Sample Input
5 3 3 3 3 3 5 6 1 2 3 4 5 6 5 0
Sample Output
3 3
Data Constraint
对20%的数据,有n<=10;
对40%的数据,有n<=100;
对100%的数据,有n<=1000,每种珍珠数目不超过2000,1<=M<=100。
解析:题意很显然,这题有三种做法:
1、开个优先队列,每次取出前5个-1,再返回,这种做法显然会超时。
2、打一个堆优化,AC。
3、逆推,二分查找枚举答案,判断答案的合法性。
#include <bits/stdc++.h>
using namespace std;
int a[10001];
int n,m,sum=0,ans;
bool cmp (int a,int b)
{
return a<b;
}
bool check (int mid)//将前(n-m)个珠子的和t求出,枚举最大的m个珠子,若a[i]<mid就用t中的珠子去补,能补完就可行
{
int t=0;
for (int i=1;i<=n-m;i++)
t+=a[i];
for (int i=n-m+1;i<=n;i++)
{
t-=mid-a[i];
if (t<0) return false;
}
return true;
}
int main()
{
while (1<2)
{
cin>>n;
sum=0;
if (n==0) break;
//int t=0;
memset (a,0,sizeof(a));
for (int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
sort (a+1,a+n+1,cmp);
cin>>m;
int l=1,r=sum/m;//sum为总珠子的数目,m是一个项链要求的珠子数目。;
if (m>n) {
cout<<0<<endl;
continue;
}
while (l<=r)
{
int mid=(l+r)/2;
if (check(mid))
{
ans=mid;
l=mid+1;
}
else
{
ans=mid-1;
r=mid-1;
}
}
cout<<ans<<endl;
}
}