二分答案练习
一、愤怒的羊驼
题目描述
输入描述
输出描述
样例1
提示
参考答案
#include <iostream>
#include <algorithm>
using namespace std;
int N, C;
int mid;
int pos[100005];
// 按照当前的距离 mid,计算是否能放下 c 只羊驼
bool check(int mid)
{
int cnt = 1; // 记录放羊驼的数量
int prev = pos[1]; // 记录第一个隔间的位置
// 依次遍历第二到第n个隔间
for (int i = 2; i <= N; i++)
{
// 如果下一个隔间到当前隔间的距离大于等于 mid
if (pos[i]-prev >= mid)
{
cnt++; // 可以放一只羊驼,记录数量
prev = pos[i]; // 更新当前隔间的位置为下一个隔间
}
}
// 返回当前距离 mid 是否能够放下 c 只羊驼
return (cnt >= C);
}
int main()
{
// 输入
cin >> N >> C;
for (int i = 1; i <= N; i++)
{
cin >> pos[i];
}
sort(pos+1, pos+N+1); // 将隔间位置从小到大排序
int l = 1; // 最小距离为1
int r = pos[N] - pos[1]; // 最大距离为最后一个隔间位置减去第一个隔间位置
int ans = 0;
// 二分查找最大的最近距离
while (l <= r)
{
mid = (l+r) / 2;
if (check(mid))
{
ans = mid;
l = mid+1;
}
else
{
r = mid-1;
}
}
// 输出最近距离
cout << ans;
return 0;
}
二、偷吃西瓜
题目描述
输入描述
输出描述
样例1
提示
参考答案
#include <iostream>
using namespace std;
int N, H;
int ans;
int a[1000005];
// 检查当前速度 mid 是否可以在 H 小时内吃完
bool check(int mid)
{
long long t = 0;
for (int i = 1; i <= N; i++)
{
t += (a[i]+mid-1)/mid;
}
return (t <= H);
}
int main()
{
// 输入
cin >> N >> H;
for (int i = 1; i <= N; i++)
{
cin >> a[i];
ans = max(ans, a[i]);
}
// 二分
int l = 1, r = ans;
while (l <= r)
{
int mid = (l+r) / 2;
if (check(mid))
{
ans = mid;
r = mid-1;
}
else
{
l = mid+1;
}
}
// 输出
cout << ans;
return 0;
}
三、丢沙包
题目描述
输入描述
输出描述
样例1
提示
参考答案
#include <iostream>
#include <algorithm>
using namespace std;
int n, c;
int pos[100005];
// 按照当前的距离 mid 计算是否能丢 c 只沙包
bool check(int mid)
{
// 记录第一个沙包的位置和放沙包的数量
int prev = pos[1];
int cnt = 1;
// 遍历第二到第n个位置
for (int i = 2; i <= n; i++)
{
// 如果下一个位置到当前位置的距离 >= mid
if (pos[i] - prev >= mid)
{
cnt++; // 下一个位置可以丢一个沙包
prev = pos[i]; // 更新当前的位置为下一个位置
}
}
// 返回当前距离 mid 是否能够丢 c 个沙包
return (cnt >= c);
}
int main()
{
// 输入
cin >> n >> c;
for (int i = 1; i <= n; i++)
{
cin >> pos[i];
}
// 二分
sort(pos+1, pos+n+1);
int mid, ans = 0;
int l = 1, r = pos[n]-pos[1];
while (l <= r)
{
mid = (l+r) / 2;
if (check(mid))
{
ans = mid; // 更新答案
l = mid+1; // 搜索更大的距离
}
else
{
r = mid-1; // 减小距离
}
}
// 输出
cout << ans;
return 0;
}
四、木材加工
题目描述
输入描述
输出描述
样例1
提示
参考答案
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n, k;
int len[100005];
// 判断当前长度 mid 能切段数是否满足要求段数 m
bool check(int mid)
{
// 记录切割得到的小段数量
int cnt = 0;
for (int i = 1; i <= n; i++)
{
cnt += len[i]/mid;
}
// 判断是否可以切出
return (cnt >= k);
}
int main()
{
freopen("wood.in", "r", stdin);
freopen("wood.out", "w", stdout);
// 输入
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> len[i];
}
// 二分
sort(len+1, len+n+1);
int mid, ans;
int l = 1, r = len[n];
while (l <= r)
{
mid = (l+r) / 2;
if (check(mid))
{
ans = mid;
l = mid+1; // 继续搜索更大的 l
}
else
{
r = mid-1; // 减小 l
}
}
// 输出
cout << ans;
fclose(stdin);
fclose(stdout);
return 0;
}
五、路标设置
题目描述
输入描述
输出描述
样例1
提示
参考答案
#include <iostream>
using namespace std;
int ans;
int maxn;
int l, n, k;
int a[100005];
int check(int mid)
{
int cnt = 0;
for (int i = 2; i <= n; i++)
{
int tmp = a[i]-a[i-1];
while (tmp > mid)
{
tmp -= mid;
cnt++;
}
}
return (cnt <= k);
}
int main()
{
// 输入
cin >> l >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
maxn = max(maxn, a[i]-a[i-1]);
}
// 二分
int mid;
int l = 1, r = maxn;
while (l <= r)
{
mid = (l+r) / 2;
if (check(mid))
{
ans = mid;
r = mid-1;
}
else
{
l = mid+1;
}
}
cout << ans;
return 0;
}