Description

\(n\) 个客人,分别在 \(t_i\) 时刻到访,在每一个客人到访时,暖炉必须是打开的。暖炉初始是关闭的,并且最多只能打开 \(k\) 次。求开着暖炉的最小时间。保证不会有两个客人在同一时间到访。

Solution

假设 \(t_i\) 已经升序排序,那么显然有 \(n-1\) 个间隔是可以选择的,第 \(i\) 个间隔的长度是 \(t_{i+1}-t_i-1\)

其中,我们最多可以拿掉 \(k-1\) 个区间,显然我们会拿最大的 \(k-1\) 个,于是对其排序即可。


当然,设 \(f[i][j]\) 表示 \([t_i,t_i+1)\) 后,已经用了 \(j\) 次开启,需要的最短时间,这时 \(O(n^2)\) 的 dp 也是显然的。


口胡一个费用流的做法,建立 \(S,S',T\),每个客人当一对点 \(i,i'\),按时间排序后依次连线 \(i' \to i+1\),费用为时差。

\(S \to S'\) 限制总流量 \(k\)\(S' \to i\)\(i' \to T\),费用为 \(0\)

\(i \to i'\),费用为 \(-M\),其中 \(M\) 是一个很大的负数,通过这样的方式来保证这样的每条边都会被流过。

没验证过,仅供参考。


贪心 CODE

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1000005;

int n,k,t[N],a[N];

signed main()
{
    ios::sync_with_stdio(false);
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>t[i];
    sort(t+1,t+n+1);
    for(int i=1;i<n;i++) a[i]=t[i+1]-t[i]-1;
    sort(a+1,a+n);
    reverse(a+1,a+n);
    int ans=t[n]-t[1]+1;
    for(int i=1;i<k;i++) ans-=a[i];
    cout<<ans<<endl;
}

相关文章:

  • 2021-11-09
  • 2022-01-27
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-01-10
  • 2021-11-23
  • 2021-12-18
猜你喜欢
  • 2022-01-23
  • 2022-01-10
  • 2022-12-23
  • 2022-12-23
  • 2022-01-13
  • 2021-11-20
  • 2021-08-18
相关资源
相似解决方案