【洛谷 P1824】进击的奶牛 题解(二分答案+循环)

进击的奶牛

题目描述

Farmer John 建造了一个有 N N N 2 ≤ N ≤ 1 0 5 2 \leq N \leq 10 ^ 5 2N105) 个隔间的牛棚,这些隔间分布在一条直线上,坐标是 x 1 , x 2 , ⋯   , x N x _ 1, x _ 2, \cdots, x _ N x1,x2,,xN 0 ≤ x i ≤ 1 0 9 0 \leq x _ i \leq 10 ^ 9 0xi109)。

他的 C C C 2 ≤ C ≤ N 2 \leq C \leq N 2CN)头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John 想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?

输入格式

1 1 1 行:两个用空格隔开的数字 N N N C C C

2 ∼ N + 1 2 \sim N+1 2N+1 行:每行一个整数,表示每个隔间的坐标。

输出格式

输出只有一行,即相邻两头牛最大的最近距离。

样例 #1

样例输入 #1

5 3
1
2
8
4
9

样例输出 #1

3

思路

首先从输入中读取牛棚数量 n n n和牛的数量 c c c,然后读取每个牛棚的位置,并将它们存储在数组 a a a中。对数组进行排序,确保牛棚的位置是按照从小到大的顺序排列。

定义一个check函数,用于检查给定的最小距离 x x x是否可行。函数通过遍历每个牛棚,计算相邻牛棚的距离,并累加这些距离。每当累加的距离大于或等于 x x x时,就将牛的数量增加一,并将累加的距离重置为0。最后,如果牛的数量大于或等于 c c c,则返回真,否则返回假。

main函数中,定义了两个变量 l l l r r r,分别表示最小距离的可能范围。开始时, l l l设置为0, r r r设置为一个非常大的数(INF)。然后进行二分搜索,每次取 l l l r r r的中点作为检查的最小距离,如果check函数返回真,说明当前的最小距离可行,但可能存在更大的最小距离,因此将 l l l设置为中点;否则,说明当前的最小距离不可行,可能需要减小最小距离,因此将 r r r设置为中点。重复这个过程,直到 l l l r r r的差距小于1。

在循环结束时,l 是最后一个满足条件的值,而 r 是第一个不满足条件的值。由于目标是找到满足条件的最大值,所以选择输出 l,即满足条件的最大最小距离。


AC代码

#include <algorithm>
#include <iostream>
#define INF 0x3f3f3f3f
#define AUTHOR "HEX9CF"
using namespace std;

const int N = 1e5 + 7;

int n, c;
int a[N];

bool check(int x) {
	int i = n;
	int d = 0;
	int cnt = 1;
	for (int i = 2; i <= n; i++) {
		d += a[i] - a[i - 1];
		if (d >= x) {
			cnt++;
			d = 0;
		}
	}
	// cout << cnt << endl;
	return cnt >= c;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> n >> c;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	sort(a + 1, a + n + 1);
	int l = 0;
	int r = INF;
	while (l + 1 < r) {
		int mid = (l + r) >> 1;
		if (check(mid)) {
			// 牛偏多,增大距离
			l = mid;
		} else {
			// 牛偏少,缩小距离
			r = mid;
		}
		// cout << l << " " << r << endl;
	}
	cout << l << endl;
	return 0;
}

  • 29
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
过河卒是一个典型的动态规划问题。首先,我们将整个棋盘看作一个二维数组,数组的每个元素表示到达该位置的路径数目。然后,我们根据题目给出的条件,逐步更新数组中的元素,直到计算出到达目标位置的路径数目。 具体的解题思路如下: 1. 首先,我们可以将马的位置设置为0,表示无法经过该位置。 2. 然后,我们根据马的位置,更新数组中的元素。对于二维数组中的每个位置,我们根据左边和上边的位置来计算到达当前位置的路径数目。具体地,如果左边和上边的位置都可以经过,那么到达当前位置的路径数目就等于左边和上边位置的路径数目之和。如果左边或上边的位置无法经过,那么到达当前位置的路径数目就等于左边或上边位置的路径数目。 3. 最后,我们输出目标位置的路径数目。 下面是洛谷p1002过河卒题解C++代码: ```cpp #include <bits/stdc++.h> using namespace std; int main() { long long a[21][21]; int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; // 初始化数组,马的位置设置为0 for(int i=0; i<=20; i++) { for(int k=0; k<=20; k++) { a[i][k] = 1; } } a[x2][y2] = 0; // 根据马的位置更新数组中的元素 if(x2 >= 2 && y2 >= 1) a[x2-2][y2-1] = 0; if(x2 >= 1 && y2 >= 2) a[x2-1][y2-2] = 0; if(x2 <= 18 && y2 >= 1) a[x2+2][y2-1] = 0; if(x2 <= 19 && y2 >= 2) a[x2+1][y2-2] = 0; if(x2 >= 2) a[x2-2][y2+1] = 0; if(x2 >= 1) a[x2-1][y2+2] = 0; if(y2 >= 1) a[x2+2][y2-1] = 0; if(y2 >= 2) a[x2+1][y2-2] = 0; // 动态规划计算路径数目 for(int i=1; i<=20; i++) { for(int k=1; k<=20; k++) { if(a[i][k] != 0) { a[i][k] = a[i-1][k] + a[i][k-1]; } } } // 输出目标位置的路径数目 cout << a[x1][y1] << endl; return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值