二分模板
二分答案本质已经出来了
题型1,最值最化
就是每次根据m次比较,找最值(只要有m次操作,有序单调基本都可用)
最小最大和最大最小略有不同(走的方向更新解的方向刚好相反,理解了本质都一样)
关键和难点还是写judge函数怎么找到每次枚举答案的次数,怎么找到写出m次。
1 while(l<=r)//最小值最大化 2 { 3 ll mid=(l+r)/2; 4 5 int t=judge(mid); 6 if(t<=m)//t<=是不变的,<=m都是可行解,ans必定放在这里更新 7 { 8 l=mid+1;//往右区间高方向试试能不能更大解 9 ans=mid; 10 } 11 else r=mid-1; 12 } 13 14 while(l<=r)//最大值最小化 15 { 16 ll mid=(l+r)/2; 17 18 int t=judge(mid); 19 if(t<=m)//t<=m是不变的,<=m次都是可行解,ans必定放在这里更新 20 { 21 r=mid-1;//往左区间低方向试试能不能更小解 22 ans=mid; 23 } 24 else l=mid+1; 25 }
题型2,有小数点类型(保留几位小数==)的求解,这种求一个答案,不断试答案枚举答案!
与题型1略有不同,到大致一样,遇到满足的即可马上退出,不像题型1一样遇到满足的不退出再试试有没有更大(小)的更优解!
小车问题模板代码(银行贷款问题也一样)(比较考验代码能力和思维能力==分析解决问题的能力)
1 #include <iostream> 2 #include <iomanip> 3 using namespace std; 4 5 int main() 6 { 7 ios::sync_with_stdio(false); cin.tie(0); 8 9 double s,a,b; 10 cin>>s>>a>>b; 11 12 double ans=0; 13 double l=0,r=s; 14 while(l<=r) 15 { 16 double mid=(l+r)/2; 17 18 double t2=mid/b+(s-mid)/a; 19 double t1=mid/b+(mid-a*mid/b)/(a+b)+(s-a*mid/b-a*(mid-a*mid/b)/(a+b))/b; 20 double t=t2-t1; 21 22 if(t>=-0.000001 && t<=0.000001) 23 { 24 ans=mid; 25 break; 26 } 27 else 28 { 29 if(t<-0.000001) r=mid-0.000001; 30 else if(t>0.000001) l=mid+0.000001; 31 } 32 33 } 34 //if(l>r) ans=r; 35 36 //cout<<setiosflags(ios::fixed)<<setprecision(6)<<ans<<endl; 37 double p=ans/b+(s-ans)/a; 38 cout<<setiosflags(ios::fixed)<<setprecision(6)<<p<<endl; 39 40 41 return 0; 42 }