P1607 [USACO09FEB]庙会班车Fair Shuttle 贪心

  

逛逛集市,兑兑奖品,看看节目对农夫约翰来说不算什么,可是他的奶牛们非常缺乏锻炼——如果要逛完一整天的集市,他们一定会筋疲力尽的。所以为了让奶牛们也能愉快地逛集市,约翰准备让奶牛们在集市上以车代步。但是,约翰木有钱,他租来的班车只能在集市上沿直线跑一次,而且只能停靠N(1 ≤N≤20000)个地点(所有地点都以1到N之间的一个数字来表示)。现在奶牛们分成K(1≤K≤50000)个小组,第i 组有Mi(1 ≤Mi≤N)头奶牛,他们希望从Si跑到Ti(1 ≤Si<Ti≤N)。

由于班车容量有限,可能载不下所有想乘车的奶牛们,此时也允许小里的一部分奶牛分开乘坐班车。约翰经过调查得知班车的容量是C(1≤C≤100),请你帮助约翰计划一个尽可能满足更多奶牛愿望的方案。

输入输出格式

输入格式:

【输入】

第一行:包括三个整数:K,N和C,彼此用空格隔开。

第二行到K+1行:在第i+1行,将会告诉你第i组奶牛的信息:Si,Ei和Mi,彼

此用空格隔开。

输出格式:

【输出】

第一行:可以坐班车的奶牛的最大头数。

输入输出样例

输入样例#1:  复制
8 15 3
1 5 2
13 14 1
5 8 3
8 14 2
14 15 1
9 12 1
12 15 2
4 6 1
输出样例#1:  复制
10


把车看成很多教室 每个时间点有C个教室 然后往里面装牛就可以了 贪心思路很简单

朴素算法超时了: 7000ms
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=1e5+6;

struct node
{
    int l,r,num;
}s[N];
int sum[N],n,m,C;

bool cmp(node a,node b)
{
    return a.r==b.r?a.l<b.l:a.r<b.r;
}
int main()
{
    RIII(n,m,C);
    rep(i,1,n)RIII(s[i].l,s[i].r,s[i].num);
    sort(s+1,s+1+n,cmp);

    int ans=0;

    rep(i,1,n)
    {
        int minn=inf;
        rep(j,s[i].l,s[i].r-1)
        minn=min(C-sum[j],minn);
        minn=min(minn,s[i].num);

        ans+=minn;
        rep(j,s[i].l,s[i].r-1)sum[j]+=minn;
    }
    cout<<ans;

    return 0;
}
View Code

加两条剪枝就能过 250ms

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=50007;

struct node
{
    int l,r,num;
}s[N];
int sum[N],n,m,C;

bool cmp(node a,node b)
{
    return a.r==b.r?a.l<b.l:a.r<b.r;
}
int main()
{
    RIII(n,m,C);
    rep(i,1,n)RIII(s[i].l,s[i].r,s[i].num);
    sort(s+1,s+1+n,cmp);

    int ans=0;

    rep(i,1,n)
    {   
        if(sum[ s[i].l ]>=C)continue;//剪枝
        int minn=inf;
        rep(j,s[i].l,s[i].r-1)
        {
            minn=min(C-sum[j],minn);
            if(minn==0)break;
        }
        if(minn==0)continue;//剪枝
        
        minn=min(minn,s[i].num);

        ans+=minn;
        rep(j,s[i].l,s[i].r-1)sum[j]+=minn;
    }
    cout<<ans;

    return 0;
}
View Code

 也可以用线段树来做  维护一下最大值就可以了







猜你喜欢

转载自www.cnblogs.com/bxd123/p/10982027.html