您的位置:首页 > 其它

二分法入门(二)——POJ 3258,2976;HDU 4430;CodeForces 535C;Gym 101194D;ACdream 1066

2017-02-19 11:28 459 查看

1.Bet ACdream - 1066

题意就是每次赌博有不同的可以买(买大买小这样的),每种有自己的赔率(赢了的回报为投入的钱y*回报率a[i]),每次赌博只能有一种是有回报的,要你求出最坏情况回报最大的值,策略就是把总金额y分成y[1],y[2],y[3]….使得y[1]*a[1]==y[2]*a[2]==……这样不论是哪一种获得回报你都会得到相同的回报,二分答案,然后判断钱能不能这样买。

#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
double r,l,mid;
int n;
double money;
double c[105];
int main(){
while(~scanf("%d",&n)){
for(int i=0;i<n;i++){scanf("%lf",&c[i]);}
scanf("%lf",&money);
l=0,r=100000;
while(r-l>0.00001){
mid=(l+r)/2;
double cnt=0;
for(int i=0;i<n;i++){
cnt+=mid/c[i];
}
if(cnt>money){r=mid;}
else{l=mid;}
}

printf("%.2lf\n",mid);
}

return 0;
}


River Hopscotch POJ - 3258

最大化最小值,二分题里很经典的一种了,跳石子,删去一些石子使得跳跃距离的最小值最大,最后一块不能删(起点和终点)。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
int l,n,m;
int lef,righ,mid;
int a[50050];
int main(){
while(~scanf("%d%d%d",&l,&n,&m)){
lef=0,righ=1000000001;
for(int i=00;i<n;i++){
scanf("%d",&a[i]);
}
a
=l;
sort(a,a+n+1);
while(righ-lef>1){
int mid=(righ+lef)/2;
int cnt=0,used=0;
bool yes=1;
for(int i=0;i<=n;i++){
if(a[i]-cnt<mid){
if(i==n||used==m){yes=0;break;}
else{used++;}
}
else{cnt=a[i];}
}
if(yes){lef=mid;}
else{righ=mid;}
}
printf("%d\n",lef);
}

return 0;
}


Dropping tests POJ - 2976



之前写过很类似的题,最大化平均值,通常策略就是二分答案再依据答案排序贪心选择,判断能不能满足mid。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
int n,m;
double lef,righ,mid;
int a[1005],b[1005];
double c[1005];
bool cmp(double a,double b){return a>b;}

int main(){
while(scanf("%d%d",&n,&m),m+n){
m=n-m;
lef=0,righ=100;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<n;i++){
scanf("%d",&b[i]);
}
for(int k=0;k<100;k++){
mid=(righ+lef)/2;
for(int i=0;i<n;i++){
c[i]=(double)a[i]*1.0*100-(double)b[i]*1.0*mid;
}
sort(c,c+n,cmp);
double cnt=0;
for(int i=0;i<m;i++){
cnt+=c[i];
}
if(cnt>=0){lef=mid;}
else{righ=mid;}
}
printf("%.0lf\n",mid);
}

return 0;
}


Yukari’s Birthday HDU - 4430

以同心圆的方式给生日蛋糕插蜡烛,总共r圈,最内圈为b支蜡烛的情况下,第i圈插的蜡烛的数量为b^i,数量不能多也不能少,圆心可以插一根蜡烛也可以不插,求r*b的最小值。

因为蜡烛每一圈数量增长的速度非常快,所以r到50就足够满足数据范围了,枚举r然后寻找对应的b的最小值就行。

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
long long n;
long long r, lk, rk, midk;
int main(){
while (cin >> n){
n;
long long ss = n - 1, a_r = 1, a_k = n - 1;
for (int r = 2; r <= 50 && r <= n; r++){
lk = 1; rk = 1000001;
bool yes = 0;
while (rk - lk > 1){
midk = (rk + lk) / 2;
long long cnt = 1;
long long ans = 0;
for (int i = 1; i <= r; i++){
ans += (cnt *= midk);
if (ans > n)break;
}
if (ans == n || ans == n - 1){
yes=1; rk = midk; break;
}
if (ans > n){ rk = midk; }
else{ lk = midk; }
}
if (yes){
if (r*rk < ss || (r*rk == ss&&r < a_r)){ ss = r*rk; a_r = r; a_k = rk; }
}
}
cout << a_r << " " << a_k << endl;
}
return 0;
}


Tavas and Karafs CodeForces - 535C

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
long long A, B, n;
long long l, t, m;
int main(){
while (cin>>A>>B>>n){
for (int k = 0; k < n; k++){
cin >> l >> t >> m;
if (t < (A + (l - 1)*B)){ printf("-1\n"); }
else{
long long beg = l, endd = (t - A) / B + 2;
while (endd - beg>1){
long long mid = (beg + endd) / 2;
long long cnt = m*t;
long long sss = ((A + (l - 1)*B) + (A + (mid - 1)*B))*(mid - l + 1) / 2;
if (cnt >= sss){ beg = mid; }
else{ endd = mid; }
}
printf("%d\n", beg);
}
}
}

return 0;
}


Ice Cream Tower Gym - 101194D



构造冰淇凌塔需要下面一块是上面的两倍以上,给出n个冰淇凌球,要求塔高为k,问能构造出多少个冰淇凌塔,排序,二分可以构造出来的数量,然后贪心判断结果,我用的优先队列,先把前mid个球加入队列作为mid个塔的顶,然后顺序遍历数组,每次就与优先队列的top(塔高最小且最下面的球的面积最小)的比较能否满足,满足就pop队列顶然后push({s,h+1})进去,这是一种比较直观的做法,但是跑出来时间有点久,其实判断满足mid的时候也可以lower_bound当前球两杯大小来寻找,速度更快。

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
int n, k;
long long b[300005];
struct ice{
long long maxn;
int h;
bool operator <(const ice b)const{
if (h == b.h){ return maxn>b.maxn; }
return h > b.h;
}
};
priority_queue<ice> que;

int main(){
int t;
scanf("%d", &t);
for(int cas=1;cas<=t;cas++){
//cin >> n >> k;
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i++){
cin >> b[i];
//scanf("%lld", &b[i]);
}
sort(b, b + n);
int beg = 0, endd = n / k+3;
while (endd - beg>1){
int mid = (endd + beg) / 2;//totalnum
for (int i = 0; i < mid&&i<n; i++){
que.push({ b[i], 1 });
}
for (int i = mid; i < n; i++){
ice cnt = que.top();
if (b[i] >= 2 * cnt.maxn){
que.pop();
que.push({ b[i], cnt.h + 1 });
}
}
int total = 0;
while (!que.empty()){
if (que.top().h >= k)total++;
que.pop();
}
if (total < mid){ endd = mid; }
else{ beg = mid; }
}
cout << "Case #" << cas << ": " << beg << endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: