二分答案(by jie)
目录
--------------------------------
1. 前言:
二分答案顾名思义就是二分出答案来验证
通俗一点来说就是在[1,∞]上
每次取中间点,猜答案..
把答案作为已知条件
判断答案是否满足题意..
从而求证出所需解的过程
2. 方法:
var
l,r,m:longint;
ans:longint;
begin
l:=1; r:=n;
ans:=0;
while l<=r do
begin
m:=(l+r) shr 1;
if pd(m) then begin ans:=m; r:=m-1; end
else l:=m+1
end;
writeln(ans);
end;
3. 典型例题
例题1奇怪的函数
问题描述
使得xx达到或超过n位数字的最小正整数x是多少?
输入数据
输入一个正整数n。
输出数据
输出使得xx达到n位数字的最小正整数x。
输入样例
11
输出样例
10
时间限制
各测试点1秒
内存限制
你的程序将被分配32MB的运行空间
数据规模
n<=2 000 000 000
-----------------------------------------------------------------------------------------------------------------
问题分析:
1.首先要知道换底公式来求位数:
位数=ln(xx)/ln(10)+1
=x*(ln(x)/ln(10))
2.确定二分方案:
l:=1; r:=max;
while l<=r do
begin
mid:=(l+r) shr 1;
if js(mid)>=n then
begin
ans:=mid;
r:=mid-1;
end
else
l:=mid+1;
end;
writeln(ans);
3.小结:
最基础的二分题只用知道换底公式来求位数就可以做出来了
代码:ctrl+鼠标左键点标题奇怪的函数
===================================================================
例题2:关押罪犯
题目描述
S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件。
每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里。公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。
在详细考察了N 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。那么,应如何分配罪犯,才能使Z 市长看到的那个冲突事件的影响力最小?这个最小值是多少?
【输入输出样例说明】
罪犯之间的怨气值如下面左图所示,右图所示为罪犯的分配方法,市长看到的冲突事件影响力是3512(由2 号和3 号罪犯引发)。其他任何分法都不会比这个分法更优。
【数据范围】
对于30%的数据有N≤ 15。
对于70%的数据有N≤ 2000,M≤ 50000。
对于100%的数据有N≤ 20000,M≤ 100000。
输入格式
输入文件的每行中两个数之间用一个空格隔开。
第一行为两个正整数N 和M,分别表示罪犯的数目以及存在仇恨的罪犯对数。
接下来的M 行每行为三个正整数aj,bj,cj,表示aj 号和bj 号罪犯之间存在仇恨,其怨气值为cj。数据保证1<aj=<=bj<=N ,0 < cj≤ 1,000,000,000,且每对罪犯组合只出现一次。
输出格式
共1 行,为Z 市长看到的那个冲突事件的影响力。如果本年内监狱中未发生任何冲突事件,请输出0。
样例输入
4 6
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884
样例输出
3512
-----------------------------------------------------------------------------------------------------------------
问题分析:
1.属于最大值最小问题:
最大值最小问题一般来说都是二分答案求值
是这样看的
求所有怨气中的最大值的最小值;
2.具体实现:
二分+染色
先二分出一个怨气值,将怨气值作为已知条件
来验证答案是否正确从而求解的过程;
3.小结:
一般二分都不会单独拿出来考,否则就显得太菜了
它往往结合着染色,最短路,DP等等来考
这道就是二分加染色
代码:ctrl+鼠标左键点标题NOIP2010关押罪犯;
==================================================================
例题3:电话网络(phone)
【题目描述】
绿化工程终于完成,整个园区生机勃勃。但是,很不幸的是,在绿化过程中,工人们和进出的车辆将铺设好的电话线全部破坏了。Neyc的领导很生气,问题很严重。为了保住面子,工程队负责人,希望尽快恢复园区的电信,他把这个任务交给了你。
已知,园区周围分布N(1<=n<=1000)根按1…n排列的电话线杆,电话线杆之间可以拉电话线。第i对电话线杆的两个端点分别为Ai,Ri,它们间的距离为Li(1<=li<=1000000)。数据中保证每对最多只出现一次。编号为1的电话线杆已经接入了全国的电话网络,整个园区的电话线全部连到了编号为N的电话线杆上。也就是说,你的任务仅仅是找一条将1号和N号电话线杆连起来的路径,其余的电话线杆并不一定要连入电话网络。
绿化工程的负责人与电信公司协商后,电信公司决定免费为园区连接K(0<=k<n)对由你指定的电话线杆。对于此外的那些电话线,就必需为它们付费,总费用等于其中最长的电话线长度(每根电话线仅连接一对电话线杆),其它长度不付费。如果需要连接的电话线杆不超过K对,那么总支出为0。
现在,你就要设计一个费用最少的方案。最后,计算出将电话线引到园区最少需要花多少钱?
【输入格式】
输入文件的第一行包含三个用空格隔开的整数:N ,P和K。
第二行到第P+1行:每行分别都为三个用空格隔开的整数:Ai Bi和Li。
【输出格式】
输出文件仅包含一个整数,表示在这项工程上的最小支出。如果任务不可能完成,则输出-1。
【样例输入】
5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6
【样例输出】
4
-----------------------------------------------------------------------------------------------------------------
问题分析
1.属于求最大值最小的问题:
和例题2相同,二分答案验证答案
是这样看的
求所有长度中的最大值的最小值
2.具体实现:
二分+最短路径
根据题意就是求1~n的最短距离
超过二分出的答案则dist[j]:=min(dist[i]+1,dist[j])
判断if dist[n]-k>0 then exit(false)
else exit(true);
3.小结:
属于二分+最短路的问题
再次强调:
将二分出的答案当做已知量,判断是否可行
代码:ctrl+鼠标左键点标题电话网络(phone)
===================================================================
例题4:SOFTWARE
【题目描述】
一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成m个模块,由公司里的技术人员分工完成,每个技术人员完成同一软件的不同模块的所用的天数是相同的,并且是已知的,但完成不同软件的一个模块的时间是不同的,每个技术人员在同一时刻只能做一个模块,一个模块只能由一个人独立完成而不能由多人协同完成。一个技术人员在整个开发期内完成一个模块以后可以接着做任一软件的任一模块。写一个程序,求出公司最早能在什么时候交付软件。
【输入】
输入文件第一行包含两个由空格隔开的整数n和m,其中1≤n≤100,1≤m≤100。接下来的n行每行包畲两个用空格隔开的整数d1和d2,d1表示该技术人员完成第一个软件中的一个模块所需的天数,d2表示该技术人员完成第二个软件中的一个模块所需的天数,其中l≤d1,d2≤100。
【输出】
输出文件仅有一行包含一个整数d,表示公司最早能于d天后交付软件。
【样例】
SOFTWARE.IN
3 20
1 1
2 4
1 6
SOFTWARE.OUT
18
【样例解释】
最快的方案是第一个技术人员完成第二个软件的18个模块,用时18天,第三个技术人员完成第一个软件的18个模块,用时18天,其余的模块由第二个技术人员完成,用时12天,做完所有模块需要18天。如果第一个技术人员完成第二个软件的17个模块,第三个技术人员完成第一个软件的17个模块,其余的模块由第二个技术人员完成,需要用时18天,做完所有模块仍然需要18天,所以少于18天不可能做完所有模块。
-----------------------------------------------------------------------------------------------------------------
题目分析:
1.属于求最大值最小问题:
是这样看的
我们要求的是两个工作完成的最大天数(两个中的最大天数)的最小值
2.具体实现:
二分答案过后,出来个天数
根据这个天数设计DP方程
DP方程
f[i,j]含义:表示前i个人做j个软件1的模块最多能做多少个软件2的模块
转移:f[i,j]:=max(f[i-1,k]+(ans-(j-k)*peo[i].d1) div peo[i].d2)
if f[n,m]>=m then exit(true)
else exit(false);
3.小结:
当二分遇见了动规后对于我个人现在而言来就算比较难了
困难处:
不怎么容易想到如何通过二分出的答案来验证二分答案的最优性
本题的验证方法比较巧妙
以天数为中转条件
算出软件2在软件1做m个时软件2是否能做m个为判断条件
代码:ctrl+鼠标左键点标题SOFTWARE
4. 结语:
1.总的来说二分答案并不是个困难的内容
2.主要注意的是
1.一般的题目命题点:求最大值最小问题。
2.对二分出的答案进行转换,验证是一个难点。
3.不着么可能会单独出题,一般来说会和染色,最短路,DP等结合起来。
3.本难度属于NOIP内容,希望各位ACM/NOI/省队神牛看到后不要嘲笑我这弱菜
4.转载请标明出处http://blog.csdn.net/jie_guale(by jie于2011-10-14晚总结)