用途
- 实数二分
基础代码
模板
只需要while(l <= r){ l = mid + 1; r = mid - 1; 用一个ans记录可以的时候(can函数成立)的值即可 }
int ans = 0;
while (l <= r)
{
mid = (l + r) / 2;
if (judge(mid))
{
r = mid - 1;
ans = mid;
}
else
l = mid + 1;
}
题目
n条线缆, 长度为L[i],从n条电缆中要切割出K条长度相同的电缆,最长可以是多长?
#include <cstdio>
#include <cmath>
using namespace std;
const int M=10005;
const double inf=200005.0;
double L[M];
int n,k;
bool judge(double x)
{
int num=0;
for(int i=0;i<n;i++)
num+=(int)(L[i]/x);
return num>=k;
}
void solve()
{
double left=0,right=inf;
for(int i=0;i<100;i++) //代替while(r>l) 避免了精度问题
{ //1次循环可以把区间缩小一半,100次可以达到10^(-30)的精度
double mid=(left+right)/2;
if(judge(mid)) left=mid;
else right=mid;
}
printf("%.2f\n",floor(right*100)/100);
}
int main()
{
while(scanf("%d%d",&n,&k)!=-1)
{
for(int i=0;i<n;i++)
scanf("%lf",&L[i]);
solve();
}
return 0;
}
有m只牛,n间牛舍, 第i号牛舍在xi位置,要把每只牛放在离其他牛尽可能远的地方,即最大化两头牛的距离
(最小值最大化问题)
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn= 999999;
int n;
int m;
int a[maxn];
bool can(int x)
{
int cnt=1;
int p=0;
for(int i=1;i<n;i++)
{
if(a[i]-a[p]>=x)
{
cnt++;
p=i;
}
}
return cnt >= m;
}
int find()
{
int l=0,r=a[n-1];
int ans=0;
while(l<=r)
{
//cout<<l<<" "<<r<<endl;
int mid=(l+r)/2;
if(can(mid))
{
l=mid+1;
ans=mid;
}
else r=mid-1;
}
return ans;
}
int main()
{
// cin>>n>>m;
// for(int i=0;i<n;i++)
// cin>>a[i];
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
// cout<<find()<<endl;
printf("%d",find());
return 0;
}
n本书,每本pi;m个人
每人分到连续若干本,且每本书只分给一个人。如果有多个解决方案,请输出第一个人工作量最小的解决方案
求使得每人分到的页数和的最大值 最小
- 正确的代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1000
int *a;//保存页数
int n, m;// n 书的本数 m 人数
bool judge(int mid) // 假设 每人翻译mid页,判断是否可以完成
{
int pagesum = 0;//记录当前一个人要翻译的页数
int group = 1;//人数
for (int i = n - 1; i >= 0; i--)
{
if (pagesum + a[i] > mid)//如果当前这个人页数再多一本书会超过mid
{
pagesum = a[i];//把这本新的书给下一个人
group++;//人数++
}
else
pagesum += a[i];
}
if (group > m)//超过已有的人,这个假设 不能完成
return false;
else
return true;
}
void output(int l)
{
int group = 1;
int pagesum = 0;
bool *divider = new bool[n + 1];
for (int i = 0; i <= n; i++)
divider[i] = true;
for (int i = n - 1; i >= 0; i--)
{
if (m - group == i + 1)
break;
if (pagesum + a[i] > l)
{
pagesum = a[i];
group++;
}
else
{
divider[i] = false;
pagesum += a[i];
}
}
for (int i = 0; i < n /*- 1*/; i++)
{
cout << a[i] << " ";
if (divider[i])
cout << "/ ";
}
cout<<endl;
}
int main()
{
int t; cin >> t;
while (t--)
{
cin >> n >> m;// n 书的本数 m 人数
a = new int[n + 1];
int l = 0, r = 0, mid = 0;
for (int i = 0; i < n; i++)
{
cin >> a[i];
r += a[i];
if (l < a[i])
l = a[i];
}
int ans = 0;
while (l <= r)
{
mid = (l + r) / 2;
if (judge(mid))
{
r = mid - 1;
ans = mid;
}
else
l = mid + 1;
}
//cout << "l=" << l << " ans=" << ans << endl;
//output(l);//对
output(ans);//对
}
::system("pause");
return 0;
}
不知道为什么无法运行:
#include<iostream>
#include <algorithm>
using namespace std;
const int maxn=999999;
int n,m;//n book m people
int a[maxn];
int T;
bool can(int x)
{
int sum = 0;
int people = 1;
for(int i = n-1; i>=0; i++)
{
if(sum+a[i] > x)
{
sum=a[i];
people++;
}
else
sum+=a[i];
}
if(people>m)
return false;
else
return true;
}
int find()
{
int ans=0;
int l=0,r=0;
int mid = 0;
for(int i=0; i<n; i++)
r+=a[i];
while(l<=r)
{
mid=(l+r)/2;
if(can(mid))
{
ans = mid;
r=mid-1;
}
else
l=mid+1;
}
return ans;
}
void output(int x)
{
int people = 1;
int sum = 0;
bool divider[maxn];
for(int i = 0; i <= n; i++)
divider[i] = true;
for (int i = n - 1; i >= 0; --i)
{
if(m - people == i + 1)//剩下的的人数和剩下的书的本数相等
break;
if(sum + a[i] > x)
{
sum = a[i];
people++;
}
else//还是同一个人的书
{
divider[i] = false;//不拆开
sum += a[i];
}
}
for(int i = 0; i <= n; i++)
{
cout << a[i] << " ";
if(divider[i])
cout << "/ ";
}
cout<<endl;
}
int main()
{
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
output(find());
}
return 0;
}