题目大意:
一共有三种人,每种人的数量为b,n,c;
其每一种人的力量值为sb,sn,sc;
现在保证b+n+c是偶数,需要我们将这b+n+c个人分成(b+n+c)/2对,然后每对选手放到一个倍值为c【i】的船上,对应这艘的能力值为c【i】*(s1+s2);
现在希望我们构造出来的方案中,船的最小能力值尽可能的大。
思路:
①首先答案有二分单调性,那么我们考虑二分答案。
②如何check呢?首先我们将c【i】按照从小到大顺序排序一下,然后对应我们知道,sb<sn<sc,那么我们从最小的能力值和sb+sb开始测试是否能够合格,一共六种情况,都尝试了之后如果还不能将第i个船放上人,那么对应结果就是不可行的,否则就是可行的。
过程二分下去就行了。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{
int x,y,val;
}e[15];
int m;
int c[350000];
int num[3];
int sum[5];
int temp[5];
int Slove(int mid)
{
int cnt=0;
for(int i=1;i<=3;i++)
{
for(int j=i;j<=3;j++)
{
cnt++;
e[cnt].x=i,e[cnt].y=j,e[cnt].val=sum[i]+sum[j];
}
}
for(int i=1;i<=3;i++)temp[i]=num[i];
for(int i=1;i<=m;i++)
{
int flag=0;
for(int j=1;j<=cnt;j++)
{
if(temp[e[j].x]==0||temp[e[j].y]==0||e[j].val*c[i]<mid)continue;
if(e[j].x==e[j].y&&temp[e[j].x]<2)continue;
temp[e[j].x]--;temp[e[j].y]--;
flag=1;
break;
}
if(flag==0)return 0;
}
return 1;
}
int main()
{
while(~scanf("%d%d%d",&num[1],&num[2],&num[3]))
{
m=num[1]+num[2]+num[3];
for(int i=1;i<=3;i++)scanf("%d",&sum[i]);
m/=2;
for(int i=1;i<=m;i++)scanf("%d",&c[i]);
sort(c+1,c+1+m);
int l=0;
int r=1000000000;
int ans=0;
while(r-l>=0)
{
int mid=(l+r)/2;
if(Slove(mid)==1)
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
printf("%d\n",ans);
}
}