Cashier Employment HDU - 1529(差分约束+循环处理+二分+好题)

传送门

题意:有个店铺每天每个钟头都有所需要的人数,现在有n个应聘者,这些应聘者有个规矩,就是从ti开始工作后,然后连续工作8小时,问这个店铺每天运营者,最少需要招聘多少个人就够了?

题解:这个题差分约束条件听好想,主要在于处理24循环,以及最后的三条件处理问题,首先用s[i]来表示从0到第i小时时所需要的人数,然后对于i>=8时,可以写出s[i]-s[i-8]>=r[i],对于1<=i<8时,那么条件是:s[24]-s[i+16]+s[i]>=r[i],还有一个条件是0<=s[i]-s[i-1]<=num[i],这个拆成两个条件是s[i]-s[i-1]>=0,s[i-1]-s[i]>=-num[i],但是s[24]-s[i+16]+s[i]>=r[i]这个条件如何处理呢?可以将s[24]转移到右边,然后我们通过二分枚举这个s[24]就可以得出答案了。

附上代码:


#include<bits/stdc++.h>

using namespace std;

const int maxn=25;
const int maxm=4*maxn+50;

struct edge{
    int v,w,next;
};
edge edges[maxm];
int head[maxn],tot;

void init()
{
    memset(head,-1,sizeof(head));
    tot=0;
}

void add_edges(int u,int v,int w)
{
    edges[tot].v=v;
    edges[tot].w=w;
    edges[tot].next=head[u];
    head[u]=tot++;
}

int val[maxn],num[maxn];
int dist[maxn],cnt[maxn];
bool vis[maxn];

bool spfa()
{
    queue<int>q;
    for(int i=0;i<=24;i++){
        q.push(i);
        cnt[i]=1;dist[i]=0;vis[i]=true;
    }
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=head[u];~i;i=edges[i].next){
            int v=edges[i].v,w=edges[i].w;
            if(dist[v]<dist[u]+w){
                dist[v]=dist[u]+w;
                if(!vis[v]){
                    vis[v]=true;
                    q.push(v);
                    if(++cnt[v]>25){
                        return false;
                    }
                }
            }
        }
    }
    return true;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        init();
        for(int i=1;i<=24;i++){
            scanf("%d",&val[i]);
        }
        int m;
        scanf("%d",&m);
        memset(num,0,sizeof(num));
        for(int i=0;i<m;i++){
            int c;
            scanf("%d",&c);
            num[c+1]++;
        }
        int lb=-1,ub=m+1;
        while(ub-lb>1){
            int mid=(lb+ub)>>1;
            init();
            for(int i=1;i<=24;i++){
                add_edges(i-1,i,0);
                add_edges(i,i-1,-num[i]);
                if(i>=8){
                    add_edges(i-8,i,val[i]);
                }else{
                    add_edges(i+16,i,val[i]-mid);
                }
            }
            add_edges(0,24,mid);
            add_edges(24,0,-mid);
            if(spfa()){
                ub=mid;
            }else{
                lb=mid;
            }
        }
        if(ub==m+1){
            printf("No Solution\n");
        }else{
            printf("%d\n",ub);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/86761526