修理牛棚问题

东华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;
}
posted @ 2022-03-21 15:05  凡璞  阅读(38)  评论(0编辑  收藏  举报
1 2
3 4
5 6