来源于: 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
搜索
最新评论
|
|