• Cashier Employment 差分约束


      

    题意:有一个超市需要一些出纳员,已给出这个超市在各个时间段(0-1,1-2,2-3...共24个时间段)至少需要的出纳员数目,
    现在前来应聘有n个人,每个人都有一个固定的开始工作的时间,这也意味着从这个时间开始他要连续工作8个小时。在满足这
    个超市对出纳员的需求的前提下,让你求出最少雇佣的出纳员人数。

    need[i]表示在第 i 个小时至少也要的人数,work[i]表示应聘者中可以在第i个小时开始工作的人数,s[i]表示前i个小时雇佣的人数,

    x[ i ]表示第 i 个小时雇佣的人数。 s[i] - s[i - 1] = x[i]

    约束条件:
    (1) 0<= x[i] <= x[ i ] ,转化为 0 <= s[ i ] - s[i - 1] <= work[ i ]
    (2) i >= 8 时:need[ i ] <= x[i] + x[i - 1] + x[i - 2] + x[i - 3] + x[i - 4] + x[i - 5] + x[i - 6] + x[i - 7]
              转化为 need[ i ] <= s[ i ] - s[i - 8]
              i < 8 时:s[ i ] +s[ 24 ] -s[16 + i] >= need[i] (不清楚的可以模拟一下)
    (3)对上面的S[24]我们不知道它的值,但我们知道它表示前24个小时所雇用的总人数,也就是我们要求的结果sum.因此对于未知
              的sum,我们需要从0到n枚举sum。需要再建一条边即:s[24] - s[0] >= sum

    二分人数即可

    #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 REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f
    #define N 100000
    int head[N];
    int pos;
    struct node
    {
        int to,v,nex;
    }edge[N<<2];
    void add(int a,int b,int c)
    {
        edge[++pos].nex=head[a];
        head[a]=pos;
        edge[pos].v=c;
        edge[pos].to=b;
    }
    int n;
    int vis[N],dis[N],cnt[N];
    int work[N],need[N];
    void getmap(int k)
    {
        rep(i,1,24)
        {
            add(i-1,i,0);
            add(i,i-1,-work[i]);
            if(i>=8)
                add(i-8,i,need[i]);
            else
                add(16+i,i,need[i]-k);
        }
        add(0,24,k);
    }
    
    bool spfa(int k)
    {
        rep(i,1,24)
        vis[i]=0,dis[i]=-inf,cnt[i]=0;
        dis[0]=0;
        vis[0]=1;
        cnt[0]++;
        queue<int>q;
        q.push(0);
        while(!q.empty())
        {
            int u=q.front();q.pop();
            vis[u]=0;
            for(int i=head[u];i;i=edge[i].nex)
            {
                int v=edge[i].to;
                if(dis[v]<dis[u]+edge[i].v)
                {
                    dis[v]=dis[u]+edge[i].v;
                    if(!vis[v])
                    {
                        if(++cnt[v]>24)return 0;
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        return dis[24]==k;
    }
    
    int main()
    {
        int cas;
        RI(cas);
        while(cas--)
        {
    
            rep(i,1,24)
            RI(need[i]);
            CLR(work,0);
            int k;RI(k);
            rep(i,1,k)
            {
                int x;RI(x);work[x+1]++;
            }
            
            int L=0,R=k;
            int ans=-1;
            while(L<=R)
            {
                int mid=(L+R)>>1;
                pos=0;CLR(head,0);
                getmap(mid);
    
                if(!spfa(mid))L=mid+1;
                else R=mid-1,ans=mid;
            }
    
            if(ans!=-1)
                cout<<ans<<endl;
            else
                printf("No Solution
    ");
        }
    }
    View Code
  • 相关阅读:
    PHP $_SERVER
    一年成为Emacs高手(像神一样使用编辑器)
    mysql 加入列,改动列,删除列。
    傅立叶变换的深入理解(转帖)
    Java Swing 探索(一)LayoutManager
    Word2007怎样从随意页開始设置页码 word07页码设置毕业论文
    IIS7 和IIS8.0 HTTP 错误 500.19
    JAVA基于AE调用GP实现泰森多边形
    Servlet 第六课: Session的使用
    ORM框架
  • 原文地址:https://www.cnblogs.com/bxd123/p/10783560.html
Copyright © 2020-2023  润新知