二分题解

二分做的人不是特别多,可能是我讲的不够好,大家都没有听明白。。。。
我挂的题都不是特别难,只要你能够理解二分的思想,并能够应用的话,解决这些题应该不难。
题解只提供思想,代码靠你们自己去实现

Doors Breaking and Repairing

 给你一个n个们,每个人有一个防御值,每一次你可以对门造成x点伤害,另一个人可以恢复y点防御值。这个门的防御值小于等于0的时候,这个门就坏掉了,也没法修复了。两个人都采取最优的策略的时候,你最多可以砸坏几个门?

第一种情况:x>y 的时候,所有的门都会被你破坏
第二种情况:x<=y的时候,如果一个门的防御值小于等于x的时候,你可以直接打破,因为另一个人可以恢复防御值,你可以打防御值<=x的门的一半,因为你先手操作,所有要向上取整。

思路:将数组排序,找到防御值<=x的数量,最后输出 (x+1)/2。(暴力判断也可以,可以不用判断)
 

二分法求函数的零点

和我上课讲的基本就是一样的,题目上给的是递减函数,注意要用double类型,不要用float

 
4 Values whose Sum is 0

 注意题目给你的时间很大,但是纯暴力也不行,既然要找四个数之和为0,我们可以认为找两个数为相反数。我们可以将
1 2 数组合并,3 4 数组合并,将两个数组排序,在第一个数组里面循环,然后再第二个数组里面去寻找相反数。


Cable master

 这道也是很简单的二分答案,主要就是判断函数,判断是否能够凑够K条线段,再进行区间调整 。注意精度 double


Aggressive cows

 农夫约翰搭了一间牛棚,有N个牛舍。他要让他的M头牛住在牛舍里,一头牛住一个牛舍,要让M头牛中相邻两头牛的最小距离最大。也是二分答案,判断当前的mid是否满足条件。判断函数:第一头牛肯定放最右边,然后第二头牛与第一头牛的距离必须>=mid,第三头牛与第二头牛的距离>=mid……。判断这N个牛舍是否能够放下M头牛,并且每个距离都>=mid。 


Drying 

有一些衣服,每件衣服有一定水量,有一个烘干机,每次可以烘一件衣服,每分钟可以烘掉k滴水。每件衣服没分钟可以自动蒸发掉一滴水,用烘干机烘衣服时不蒸发。问最少需要多少时间能烘干所有的衣服。

题意上有一个点很容易忽略:所有衣服都是同步进行自动蒸发的。

特殊情况:如果烘干机可以烘干 1 滴水。还不是直接蒸发。答案就是 水分最多的那一件衣服的水量
正常情况:我们二分答案 所需时间 t,我们每件衣服可以分成两部分 t1 + t2 = t (t1为自然蒸发的时间,t2为烘干时间)
t1+k*t2>=wi(wi衣服的水量)。每件衣服除了在烘干的时候,都在蒸发,所以我们判断所有衣服烘干的时间之和是否小于等于t。由上面两个式子可以求解出t2的不等式,我们求出t2的数值(向上取整)。然后在调整区间。

 

Median

给出一个数列,然后计算数列里各个数之间的差值的绝对值,形成一个新数列,求新数列的中位数
枚举最中间的那个数,然后判断一下相减得到的数有多少个大于等于枚举的数 
如何判断上面所说的那句呢,其实不用把每个数相减,只需要排序一下,然后将当前这个数 + 枚举的那个数,然后在数组中找到大于等于这个数的第一个位置(lower_bound()),再用n减去那个数的位置就可以知道有多少个相减的结果会大于等于这个数了 
最后只需要判断一下大于等于这个枚举数的数有几个就可以了,当这个数大于等于(n * (n - 1) / 2 / 2 - 1)就表示这个枚举数是小于或者等于这个最中间值的(等于的情况就是最中间值能有多个数相减得到)

 

Dropping tests

这道题是二分+01分数规划(可以自行去百度01分数规划)
第一行输入两个数n,k,第二行输入n个数a1,a2...an,第三行输入b1,b2...bn,求在去掉k个数(ak,bk同时去掉)后(a1+a2+..+an)/(b1+b2+...bn)的最大值。
我们二分答案,\sum_{1}^{n-k} ai/\sum_{1}^{n-k} bi=ans,上面式子可以化简为\sum _{1}^{n-k} ai-bi*ans=0,我们判断这个式子 \sum _{1}^{n-k} ai-bi*ans
与0的大小调整答案上下界。

代码:

///#include<bits/stdc++.h>
///#include<unordered_map>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<list>
#include<new>
#include<vector>
#define MT(a,b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const double E=2.718281828459;
const ll mod=1e12;
const int INF=0x3f3f3f3f;

int n,k;
double a[1005],b[1005];
double c[1005];

bool judge(double x)
{
    for(int i=1;i<=n;i++)
        c[i]=a[i]-x*b[i];
    sort(c+1,c+1+n);
    double ans=0.0;
    for(int i=k+1;i<=n;i++)
        ans+=c[i];
    return ans>=0.0;
}
int main()
{
    while(scanf("%d %d",&n,&k)!=EOF,n+k)
    {
        for(int i=1;i<=n;i++)
            scanf("%lf",&a[i]);
        for(int i=1;i<=n;i++)
            scanf("%lf",&b[i]);
        double l=0.0,r=1.0;
        double mid;
        while(r-l>1e-6)
        {
            mid=(l+r)/2.0;
            if(judge(mid))
                l=mid;
            else
                r=mid;
        }
        printf("%.0f\n",r*100);
    }
    return 0;
}

 

 

 Ice Cream Tower

防AK题,题解博客:https://blog.csdn.net/qq_42671946/article/details/88757292

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值