來源于: http://hi.baidu.com/dlutnocow/blog/item/3a23c5ab17de8abccb130c31.htmlhdu 3418 二分 湊 ★★★ 這題我做不出,看edward_mj的 edward_mj那里也有一種不是二分的,就是每次不斷計算平均值,對于cnt[i]>avg的,cnt[i]=avg(去掉多余的物品) 直到沒有多余的物品。
 /**//*
題意:n種物品,每種個數為cnt[i],一個人獲得至少m種才算開心,問能是多少人開心
主要思路是將n種物品壓縮成m種(m<=n),答案就是最少的那種最大化
二分答案limit
對于每個cnt[i],如果大于limit,取為limit
最后將這n個cnt[i]累加到sum,判斷sum是否≥limit*m
(大概就是多余的不要,少的湊一下,看能不能使最少的那個>=limit)
*/
#include<cstdio>
#include<algorithm>
using namespace std;

const long long INF = 1LL<<50;//太大的話*100會溢出!!

int cnt[105];
int n,m;

bool chk(long long x)
  {
long long sum = 0;
for(int i=0;i<n;i++)
sum+=min((long long)cnt[i],x);
return sum>=x*m;
}
int main()
  {
while(~scanf("%d%d",&n,&m))
 {
for(int i=0;i<n;i++)
scanf("%d",&cnt[i]);
long long left = 0,right = INF;
while(right-left>1)
 {
long long mid = (right+left)>>1;
if(chk(mid))left=mid;
else right=mid;
}
printf("%I64d\n",left);
}
return 0;
}
zoj 3334 ★★★ 也即求能使m個醫生同時工作的最長時間 類似于湊,將n種湊成m種,使最短的那個最長
 /**//*
題意:m個醫生檢查n個病人,每個病人需要時間為t[i]
每個病人可以分為多次檢查,每次一個醫生 但不能同時被多個醫生檢查
對于醫生,要么m個同時工作,要么只有1個工作 求最少的檢查時間
當然,能m個醫生同時檢查的先同時檢查
而求n個人能被m個醫生同時檢查的最長時間跟hdu3418類似
使湊成m個的最少的那個最長!

二分枚舉時間limit
時間大于limit的變為limit
累加總時間,看是否≥limit*m

然后剩余的只能一個醫生工作了
*/
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const double EPS = 1e-12;
const int MAXN = 1005;

double t[MAXN];
int n,m;

bool chk(double limit)
  {
double sum=0.0;
for(int i=0;i<n;i++)
sum+=min(limit,t[i]);
return sum>limit*m-EPS;//>=
}
double cal(double tot)//計算能被m個醫生同時檢查的最長時間
  {
if(m>n)return 0.0;

double left = 0,right = tot;
for(int i=0;i<60;i++)
//while(right-left>EPS) --> TLE
 {
double mid=(left+right)/2.0;
if(chk(mid))left=mid;
else right=mid;
}
return left;
}
int main()
  {
while(~scanf("%d%d",&m,&n))
 {
double tot = 0.0;
for(int i=0;i<n;i++)
 {
scanf("%lf",&t[i]);
tot+=t[i];
}
printf("%.4f\n",tot-(m-1)*cal(tot));
}
return 0;
}
hdu 2730
 /**//*
題意: 一個工具箱里有n種顏色,每種50ml 。而任意三種數量為x顏色
mix能湊出數量x的灰色 現給出每種顏色的還有灰色的需求量
求最少需要購買的工具箱 跟hdu 3418類似

可二分枚舉工具箱的個數
然后再檢查能否滿足各種顏色,還有灰色的數量需求

*/
#include<cstdio>
#include<algorithm>

using namespace std;

const int INF = 10000000;

int cnt[15],_cnt[15];
int n,gray;

bool _chk(int limit)
  {
int sum = 0;
for(int i=0;i<n;i++)
sum+=min(limit,_cnt[i]);
return sum>=limit*3;
}

int cal()
  {
int left = 0,right = INF;
while(right-left>1)
 {
int mid=(right+left)>>1;
if(_chk(mid))left=mid;
else right=mid;
}
return left;
}

bool chk(int x)
  {
for(int i=0;i<n;i++)
 {
_cnt[i]=50*x-cnt[i];
if(_cnt[i]<0)return false;
}
return cal()>=gray;
}

int main()
  {
//freopen("in","r",stdin);
//freopen("out","w",stdout);
while(scanf("%d",&n),n)
 {
for(int i=0;i<n;i++)
scanf("%d",&cnt[i]);
scanf("%d",&gray);
int low = -1 , high = INF;//low=-1 high=0也可以取到
while(high-low>1)
 {
int mid=(high+low)>>1;
if(chk(mid))high = mid;
else low = mid;
}
printf("%d\n",high);
}
return 0;
}
|
|
常用鏈接
隨筆分類
Links
搜索
最新評論

|
|