修理牛棚问题
东华OJ49题 修理牛棚
题目如下
在一个暴风雨的夜晚,农民约翰的牛棚的屋顶、门被吹飞了。 好在许多牛正在度假,
所以牛棚(牛棚的总数S:1<= S<=200)没有住满。 剩下的牛一个紧挨着另一个被排成一行安置在有
屋顶的牛棚来过夜。 所以有些牛棚里有牛,有些没有。
所有的牛棚有相同的宽度,且宽度设为1。 因为有些门遗失,农民约翰需要架起新的木板作为门。
他的新木材供应者将会供应他任何他想要的长度,但是供应者只能提供有限数目的木板。 农民约翰想将他购买的木板总长度减到最少。
计算拦住所有有牛的牛棚所需木板的最小总长度。
输出所需木板的最小总长度作为的答案。
说明:拦住一个牛棚需要的木板长度为1,拦住相邻的三个牛棚则需要木板长度为3。
比如有牛的牛棚编号为:3 5 8 10 11
并且只能使用两块木板,
则第一块木板从3到5,长度为3,
第二块木板从8到11,长度为4,
因此,需要木板的总长度为7。
输入说明 :
第 1 行: M 和 C(用空格分开)
第 2 到 C+1行: 每行包含一个整数,表示牛所占的牛棚的编号。
其中:可能买到的木板最大的数目:M(1<= M<=50);
需要安置的牛的数目C(1<= C <=S)
安置后牛所在的牛棚的编号stall_number(1<= stall_number <= S)
解题思路
这道题乍一看其实会有点懵,不知如何下手,因为这涉及到了如何分组的问题。直接对牛棚编号序列进行分组没啥头绪,但是按照常理就是把离得近的一群分为一个组,按照这样的想法延申出一种解题思路:
- 我们先将相邻两个牛棚的距离算出来,保存到一个数组或者向量中
- 然后因为要分出M组,那其实就相当于切了M-1刀,那该怎么切呢?
- 按照常理切呗,离得远的切
- 所以找到距离数组中最大的M-1个距离切
这样切完就找到了M个分组,大体思路就是这样。
当然我们还需要注意一些小细节:
- 当只有一块木板时,直接用最大的牛棚编号 -最小的牛棚编号即可
- 当木板数>=牛棚个数时,最小距离就是牛棚个数
- 输入的时候牛棚编号未必有序,所以需要排序
代码实现
实现时的一些小技巧:在距离数组中,在哪切一刀,就把那个值变成1,最后将距离数组中的值全部相加,最后加1即是结果。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int M, C, x;
vector<int> cows;
vector<int> dist;
cin >> M >> C;
if (M >= C) {
cout << C;
return 0;
}
while (C--) {
cin >> x;
cows.push_back(x);
}
sort(cows.begin(), cows.end());
if (M == 1){
cout << cows.back() - cows.front() + 1 << endl;
return 0;
}
for (int i = 1; i< cows.size(); i++)
dist.push_back(cows[i] - cows[i-1]);
int idx = 0;
while (--M)
{
for (int i = 0; i < dist.size(); i++)
if (dist[i] > dist[idx])
idx = i;
dist[idx] = 1;
}
int sum = 0;
for (auto i : dist)
sum += i;
sum++;
cout << sum;
return 0;
}