[Usaco2005 Dec]Cleaning Shifts

[Usaco2005 Dec]Cleaning Shifts

给出n段区间,左右端点分别为\(l_i,r_i\),以及选取这段区间的费用\(c_i\),现在要选出若干个区间,使其完全覆盖区间\([m,e]\),询问费用之和的最小值,\(1≤n≤10000,0≤m≤e≤86399\)。

法一:

不妨把区间按左端点排序,如果在大区间范围外,可以筛除,虽然题目有保障,于是设\(f_i\)表示以第i个区间结尾,覆盖第i个区间前所有需要覆盖的位置的最少代价,于是有

\[f_i=\min_{j=1,r_j+1\geq l_i}^{i-1}\{f_j\}+1\]

边界:把覆盖大区间左端点全部手动初始化,其余无限大

答案:覆盖了大区间右端点的\(f_i\)

注意到这实际上是\(O(n^2)\)算法,但是因为n比较小,实际上这是\(C_n^2\),其实没有\(10^8\),于是可以水过。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define intmax 16843009
using namespace std;
struct interval{
    int l,r,c;
    il bool operator<(const interval&x)const{
        return l<x.l;
    }
}I[10001];
int dp[10001];
int main(){
    int n,m,e;scanf("%d%d%d",&n,&m,&e);
    for(int i(1);i<=n;++i)
        scanf("%d%d%d",&I[i].l,&I[i].r,&I[i].c);
    sort(I+1,I+n+1),memset(dp,1,sizeof(dp));
    ri int i,j;
    for(i=1;i<=n;++i)
        if(I[i].l==m)dp[i]=I[i].c;
        else break;
    while(i<=n){
        for(j=i-1;j;--j)
            if(I[j].r+1>=I[i].l)
                if(dp[j]<dp[i])dp[i]=dp[j];
        dp[i]+=I[i].c,++i;
    }int ans(intmax);
    for(i=n;i;--i)
        if(I[i].r==e)
            if(ans>dp[i])ans=dp[i];
    if(ans<intmax)printf("%d",ans);
    else puts("-1");
    return 0;
}

法二:

注意到只要出题人稍微开大数据范围,就game over了,有水过的痕迹,而且转移也不支持优化,我们只能换状态了,注意到如果法一是正解的,m,e其实可以开到long long范围,但是m,e很小,进入\(nlog^n\)范围,所以意识到可以以位置为状态。

因此设\(f_j\)为覆盖m到j位置的区间的最小费用,区间按右端点排序,枚举区间i,于是不难有

\[f_j=\min_{l_i-1\leq k\leq r_i-1}\{f_{k}\}+c_i\]

边界:\(f_{m-1}=0\),其余无限大

答案:类似法一

注意到每次我们实际上查询的已求出的f中的某一段的最小值,而已求出的不会被更新,因此我们需要区间查询,于是线段树或者树状数组可以将之优化为\(O(nlog^n)\)

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define intmax 16843009
using namespace std;
il int min(int a,int b){
    return a<b?a:b;
}
struct interval{
    int l,r,c;
    il bool operator<(const interval&x)const{
        return r<x.r;
    }
    il void read(){
        scanf("%d%d%d",&l,&r,&c),++l,++r;
    }
}I[10001];
struct segment_tree{
    int a[86400];
    struct data{
        int l,r,d;
    }t[345600];
    il void build(int p,int l,int r){
        t[p].l=l,t[p].r=r;
        if(l==r)return (void)(t[p].d=a[l]);
        int mid(l+r>>1),pl(p<<1),pr(pl|1);
        build(pl,l,mid),build(pr,mid+1,r);
        t[p].d=min(t[pl].d,t[pr].d);
    }
    il void change(int p,int x,int v){
        if(t[p].l==t[p].r)return (void)(t[p].d=v);
        int mid(t[p].l+t[p].r>>1),pl(p<<1),pr(pl|1);
        if(x<=mid)change(pl,x,v);if(x>mid)change(pr,x,v);
        t[p].d=min(t[pl].d,t[pr].d);
    }
    il int ask(int p,int l,int r){
        if(l<=t[p].l&&t[p].r<=r)return t[p].d;
        int mid(t[p].l+t[p].r>>1),pl(p<<1),pr(pl|1),ans(intmax);
        if(l<=mid)ans=min(ans,ask(pl,l,r));
        if(r>mid)ans=min(ans,ask(pr,l,r));
        return ans;
    }
}T;
int main(){
    int n,m,e,i;
    scanf("%d%d%d",&n,&m,&e),++m,++e;
    for(i=1;i<=n;++i)I[i].read();
    sort(I+1,I+n+1),memset(T.a,66,sizeof(T.a));;
    T.a[m-1]=0,T.build(1,0,e);
    for(i=1;i<=n;++i)
        T.change(1,I[i].r,min(T.ask(1,I[i].l-1,I[i].r)+I[i].c,T.ask(1,I[i].r,I[i].r)));
    int ans(T.ask(1,e,e));
    if(ans>=intmax)puts("-1");
    else printf("%d",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/a1b3c7d9/p/10958338.html

时间: 2024-08-13 16:48:28

[Usaco2005 Dec]Cleaning Shifts的相关文章

BZOJ 1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚

题目 1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚 Time Limit: 5 Sec  Memory Limit: 64 MB Description Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now require their barn to be immaculate. Farmer John, the most

[BZOJ1672][Usaco2005 Dec]Cleaning Shifts 清理牛棚

1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 953  Solved: 407 [Submit][Status][Discuss] Description Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now require the

3389: [Usaco2004 Dec]Cleaning Shifts安排值班

3389: [Usaco2004 Dec]Cleaning Shifts安排值班 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 102  Solved: 46[Submit][Status][Discuss] Description 一天有T(1≤T≤10^6)个时段.约翰正打算安排他的N(1≤N≤25000)只奶牛来值班,打扫 打扫牛棚卫生.每只奶牛都有自己的空闲时间段[Si,Ei](1≤Si≤Ei≤T),只能把空闲的奶牛安排出来值班.而且,每个

BZOJ 3389: [Usaco2004 Dec]Cleaning Shifts安排值班

题目 3389: [Usaco2004 Dec]Cleaning Shifts安排值班 Time Limit: 1 Sec  Memory Limit: 128 MB Description 一天有T(1≤T≤10^6)个时段.约翰正打算安排他的N(1≤N≤25000)只奶牛来值班,打扫 打扫牛棚卫生.每只奶牛都有自己的空闲时间段[Si,Ei](1≤Si≤Ei≤T),只能把空闲的奶牛安排出来值班.而且,每个时间段必需有奶牛在值班.  那么,最少需要动用多少奶牛参与值班呢?如果没有办法安排出合理的

Bzoj 3389: [Usaco2004 Dec]Cleaning Shifts安排值班 最短路,神题

3389: [Usaco2004 Dec]Cleaning Shifts安排值班 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 218  Solved: 86[Submit][Status][Discuss] Description 一天有T(1≤T≤10^6)个时段.约翰正打算安排他的N(1≤N≤25000)只奶牛来值班,打扫 打扫牛棚卫生.每只奶牛都有自己的空闲时间段[Si,Ei](1≤Si≤Ei≤T),只能把空闲的奶牛安排出来值班.而且,每个

bzoj 3389: [Usaco2004 Dec]Cleaning Shifts安排值班 -- 贪心

3389: [Usaco2004 Dec]Cleaning Shifts安排值班 Time Limit: 1 Sec  Memory Limit: 128 MB Description 一天有T(1≤T≤10^6)个时段.约翰正打算安排他的N(1≤N≤25000)只奶牛来值班,打扫 打扫牛棚卫生.每只奶牛都有自己的空闲时间段[Si,Ei](1≤Si≤Ei≤T),只能把空闲的奶牛安排出来值班.而且,每个时间段必需有奶牛在值班.  那么,最少需要动用多少奶牛参与值班呢?如果没有办法安排出合理的方案,

bzoj3389:[Usaco2004 Dec]Cleaning Shifts安排值班

思路:可以贪心,也可以最短路. 贪心写法:因为在保证合法的前提下,我们选择的区间一定要右端点尽量靠后才行,于是我们每次就选择一个合法的并且右端点最靠后的区间就好了(如果没有合法的输出-1即可).时间复杂度O(nlogn)(排序是nlogn的,贪心是O(n)的). #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> usi

BZOJ3389 [Usaco2004 Dec]Cleaning Shifts安排值班

裸的最短路呢... 建图还是有些微妙的...但是感觉不快啊... 每个时间点建一个点,然后我们建图分两步: (1)i 时间点向 i - 1 号时间点连一条有向边 (2)若有一头牛[l, r],则 l - 1向 r连一条边 最后答案就是dis[T] 想想就觉得非常巧妙...但是慢啊... 1 /************************************************************** 2 Problem: 3389 3 User: rausen 4 Languag

BZOJ 1672 Usaco 2005 Dec Cleaning Shifts 清理牛棚 动态规划

题目大意:有一些牛,他们的牛舍需要被打扫.有N(N <= 10000)头牛愿意打扫,从时间S到时间T,需要花费一些金钱.问若要每时每刻都有牛在打扫,至少需要花多少钱. 思路:1w的数据量不算很大,再加上时限5s,就n^2动归来做. 将牛按时间段的开始排序. 设f[i]为若取第i头牛打扫,到这头牛结束的时间最小花费是多少. 则    f[i] = min(f[i],f[j] + cost[i])  (f[i].st <= f[j].ed + 1) 最后是初值和答案的问题.由于题目中说每时每刻都有