USACO 1.4.2 修理牛棚
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.
AC代码
/* 解法一: 扩增法 */
#include
#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
#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
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
