zoukankan      html  css  js  c++  java
  • HDU [1529] || POJ [P1275] Cashier Employment

    经典的差分约束+二分答案。
    本题的难点在于如何建图。
    设x[i] 表示第i个小时可以开始工作的有多少个人。
    num[i] 表示第i个小时最少需雇佣多少人。
    s[i] 表示1...i小时实际开始工作的有多少人
    因为最后要求的是s[24]的最小值,所以我们以s为中心建图。
    因为我们求得是最小值,所以都转化成>=号的形式
    我们逐步分析题目的已知条件:

    1. 第i小时实际开始工作的人数应小于等于可以开始的人数,即 $ s[i]-s[i-1]<=x[i] $ 变成 $ s[i-1]-s[i] >=-x[i] $
    2. 第i小时实际开始工作的人数应大于等于0,即$ s[i]-s[i-1]>=0 $ .
    3. 第i小时实际工作的人数应大于等于最少需雇佣的人数,即 $ s[i]-s[i-8]>=x[i] $ .
      当i>=8 时,$ s[i]-[i-8]>=x[i] ( 当i<8 时,) s[24]+s[i]-s[i+16]>=x[i] $
      我们发现上式有三个变量,不符合差分约束的基本形式,我们可以二分答案,将上式变为 $ s[i]-s[i+16]>=x[i]-ans $
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <queue>
    #include <ctime>
    #define RST(a) memset((a),0,sizeof((a)))
    using namespace std;
    const int MAXN=50005;
    int init(){
        int rv=0,fh=1;
        char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-') fh=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9'){
            rv=(rv<<1)+(rv<<3)+c-'0';
            c=getchar();
        }
        return fh*rv;
    }
    struct edge{
        int to,nxt,dis;
    }e[MAXN];
    int T,head[MAXN],num[30],pre[30],x[30],nume,dis[30];
    void adde(int from,int to,int dis){
        e[++nume].to=to;
        e[nume].dis=dis;
        e[nume].nxt=head[from];
        head[from]=nume;
    }
    bool SPFA(){
        for(int i=0;i<=29;i++) dis[i]=-0x3f3f3f3f;
        bool f[30];
        int cnt[30];
        RST(f);RST(cnt);
        queue <int> q;
        q.push(24);
        dis[24]=0;
        f[24]=1;
        while(!q.empty()){
            int u=q.front();q.pop();
            f[u]=0;
            for(int i=head[u];i;i=e[i].nxt){
                int v=e[i].to;
                if(dis[v]<dis[u]+e[i].dis){
                    dis[v]=dis[u]+e[i].dis;
                    if(!f[v]){
                        q.push(v);
                        f[v]=1;
                        cnt[v]++;
                        if(cnt[v]>=23) return 0; 
                    }
                }
            }
        }
        if(dis[0]==-0x3f3f3f3f) return 0;
        else return 1;
    }
    bool check(int mid){
        RST(e);RST(head);nume=0;RST(dis);
        for(int i=1;i<=24;i++){
            adde(i-1,i,0);
            adde(i,i-1,-x[i]);
            if(i>=8){
                adde(i-8,i,num[i]);
            }
        }
        for(int i=0;i<8;i++){
            adde(i+16,i,num[i]-mid);
        }
        if(SPFA()) return 1;
        else return 0;
    }
    int main(){
        //freopen("in.txt","r",stdin);
        srand(time(NULL));
        T=init();
        while(T--){
            RST(num);RST(x);RST(dis);RST(head);RST(e);
            nume=0;RST(pre);
            for(int i=0;i<=23;i++) num[i]=init();
            int n=init();
            for(int i=1;i<=n;i++){
                int t=init();
                x[t]++;
            }
            pre[0]=x[0];
            for(int i=1;i<=23;i++){
                pre[i]=pre[i-1]+x[i];
            }
            int l=0,r=n,mid=0;
            while(l<=r){
                mid=(l+r)/2;
                if(check(mid)){
                    r=mid-1;
                }else l=mid+1;
            }
            if(l>=n) printf("No Solution
    ");
            else printf("%d
    ",l);
        }
        //fclose(stdin);
        return 0;
    }
    
  • 相关阅读:
    C# Devexpress GridView获得当前活动行(选中行)的索引
    C# Devexpress GridView获得当前活动行(选中行)的索引
    计算机网络学习总结(超赞!!!)
    计算机网络学习总结(超赞!!!)
    30张图带你彻底理解红黑树
    30张图带你彻底理解红黑树
    DevExpress GridView 添加和设置右键菜单
    DevExpress GridView 添加和设置右键菜单
    数据库分离和附加 (SQL Server)
    数据库分离和附加 (SQL Server)
  • 原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8143245.html
Copyright © 2011-2022 走看看