题解——修理牛棚

用户头像 发布于 2023-02-15 最后更新于 2025-11-20 14 次阅读


AI 摘要

想用最少的木板,连接散落的牛棚?这不仅仅是简单的拼接,更是一场关于“间距”的博弈!当牛棚的编号不再是障碍,而是连接的起点,我们该如何巧妙裁剪木板,让总长度缩至最短?这背后隐藏着怎样的数学智慧,等待你去揭晓。

解题思路:

此题意思为:给定木板的数量和牛棚的序号,将牛棚用木板连接起来,求出木板的总长度的最小值。

比如:

1个木板,5个牛棚分别为$3、5、8、10、11$

则用两个木板连接5个牛棚,最短解法是 $3、4 、8、10、11$ ,总长度为 $9$,即$ 11 - 3 + 1$;

再比如:

2个木板,5个牛棚分别为$3、5、8、10、11$

多出来一条木板,我们肯定想把间距最小的几个连在一起,我们先求出每个木板之间的间隔为$2、3、2、1$;

显然编号5和8之间间隔3,间隔最大,故将3去除,即$ 9 - 3 + 1 = 7$;

故最短解法是 $3、5 、8、10、11$ ,总长度为 7 ,第一块木板$(4-3+1)=3$,第二块木板长$(11-8+1)= 4$;

解题步骤:

所以本题首先要将木板按编号排序,再求出所有的木板之间的间距,将间距也排序,

先假设有一块木板,再减去最大的间距,减去次大的间距,……,直到达到最大木板数。

最后比如:

3个木板,5个牛棚分别为$2、4、6、8、7$

1.木板排序:$[2,4,6,7,8]$
2.求间距:$[2,2,1,1]$
3.间距排序:$[2,2,1,1]$
4.假设只有一块木板,总长 8-2+1=7;
5.有两块木板,减去最大间隔,总长 $7-2+1=6$;
6.有三块木板,减去次大间隔,总长 $6-2+1=5$;

来,上食用方法

#include<bits/stdc++.h>//万能头文件
using namespace std;//命名空间
int f[1314],a[1314],n,k,m;//定义
int main(){
    scanf("%d%d%d",&m,&k,&n);
    if(m>=n)//可以先特判,木板数>=牛棚数,直接就输出牛棚数
    {
        printf("%d\n",n);
        return 0;
    }
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+1+n);//对牛棚位置进行排序
    for(int i=1;i<=n;i++)
    {
        for(int j=m;j>=1;j--)//从大到小
            f[j]=min(f[j]+a[i]-a[i-1],f[j-1]+1);
        f[0]=1<<30;
        //注意!由于f[0]不参与计算,所以如果没有把它在每一个阶段后赋值为很大的数,结果必然是1
    }
    printf("%d\n",f[m]);
    //最后一定要输出f[m],因为无论怎样,木板数越多,需要盖住的和就肯定会少。不能在f[1]~f[m]中取最小值
    return 0;
}
学习,便是发现自己越来越菜的过程
最后更新于 2025-11-20