函数插值之Lagrange插值(原理及代码实现)

Module compiled with Swift 版本号 cannot be imported by the Swift 版本号 compiler

  返回  

USACO 1.4.2 修理牛棚

2021/7/20 22:58:27 浏览:

1.4.2 修理牛棚

题目考查

贪心算法, 思维考察

解题思路

本题相较上题而言, 思维难度很明显提升了. 这里给出两种供参考的解法

解法一: 扩增法

首先如果木板的数量大于牛的总数, 答案直接就是牛的总数了.

否则, 我们一定会有一些木板覆盖空牛棚, 我们想让木板总长度最小, 就相当于覆盖尽可能少的空牛棚.

假设牛棚编号从左到右依次为1~S, 我们把所有牛所在位置按编号从小到大排序, 记录在**a[]**中.
很显然, 覆盖[1, a[1])区间的空牛棚没有意义, (a[c], S]区间同理.

我们可以这样做: 记录a[i+1]到a[i]之间的空牛棚数量gapi = a[i+1] - a[i] - 1. 假设我们给每个有牛的牛棚都盖上一块长度为1板, 则会有c - 1个gap出现. 但是我们只有m块板, 只允许有m - 1个gap出现. 因此我们需要额外覆盖(c - 1) - (m - 1)个gap, 因此我们贪心选取c - m个较小的gap即可.


解法二: 删减法

PS: 本解法的变量命名同解法一.

我们不妨假设[a[1], a[c]]区间用一块木板覆盖了, 但实际上我们可以用m块, 我们可以想象成把一块木板分成了m块, 相当于我们可以删除m - 1个gap. 因此我们贪心删除最大的m - 1个gap即可.

需要注意的是, 我们一共只有c - 1个gap, 因此要么直接判断掉 m >= c的情况, 否则应注意次数不应超过c - 1次.

题目细节

  1. 当涉及到区间统计时, 我们要定义好变量的含义, 并注意是否需要±1.

AC代码

/* 解法一: 扩增法 */
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 210;
int a[N];
int main()
{
	int m, s, c; cin >> m >> s >> c;
	
	rep(i, c) scanf("%d", &a[i]);
	sort(a + 1, a + 1 + c);

	vector<int> gap;
	rep(i, c - 1) gap.push_back(a[i + 1] - a[i] - 1);
	sort(gap.begin(), gap.end());

	int res = c;
	rep(i, c - m) res += gap[i - 1];
	cout << res << endl;
	
	return 0;
}



/* 解法二: 删减法 */
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 210;
int a[N];
int main()
{
	int m, s, c; cin >> m >> s >> c;

	rep(i, c) scanf("%d", &a[i]);
	sort(a + 1, a + 1 + c);

	priority_queue<int> q;
	rep(i, c - 1) q.push(a[i + 1] - a[i] - 1);

	int res = a[c] - a[1] + 1;
	rep(i, m - 1) {
		res -= q.top(), q.pop();
		if (q.empty()) break;
	}
	cout << res << endl;

	return 0;
}

END

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号