zoukankan      html  css  js  c++  java
  • poj1275(差分约束)

    POJ1275出纳员的雇佣【差分约束】

    出纳员的雇佣

    Tehran的一家每天24小时营业的超市,需要一批出纳员来满足它的需要。超市经理雇佣你来帮他解决问题:超市在每天的不同时段需要不同数目的出纳员(例如:午夜时只需一小批,而下午则需要很多)来为顾客提供优质服务。他希望雇佣最少数目的出纳员。
    经理已经提供你一天的每一小时需要出纳员的最少数量——R(0), R(1), ..., R(23)。R(0)表示从午夜到上午1:00需要出纳员的最少数目,R(1)表示上午1:00到2:00之间需要的,等等。每一天,这些数据都是相同的。有N人申请这项工作,每个申请者I在24小时中,从一个特定的时刻开始连续工作恰好8小时,定义tI (0 <= tI <= 23)为上面提到的开始时刻。也就是说,如果第I个申请者被录取,他(她)将从tI 时刻开始连续工作8小时。
    你将编写一个程序,输入R(I)(I = 0..23)和tI (I = 1..N),它们都是非负整数,计算为满足上述限制需要雇佣的最少出纳员数目。在每一时刻可以有比对应的R(I)更多的出纳员在工作。

    输入格式:

    输入文件的第一行为测试点个数(<= 20)。每组测试数据的第一行为24个整数表示R(0),R(1),..., R(23)(R(I)<= 1000)。接下来一行是N,表示申请者数目(0 <= N <= 1000),接下来每行包含一个整数tI (0 <= tI <= 23)。两组测试数据之间没有空行。

    输出格式:

    对于每个测试点,输出只有一行,包含一个整数,表示需要出纳员的最少数目。如果无解,你应当输出“No Solution!”

    样例输入:

    1
    1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    5
    0
    23
    22
    1
    10
    

    样例输出:

    1

    时间限制:

    1s
     
    (先每个时间段加一以便C++操作)
    差分约束:
    0 <= S[i]-S[i-1]<=W[i];      // 雇佣的人数少于申请者但不能为负数
    S[i]-S[i-8]>=R[i]               // 当i>=8时,该方程成立,否则将出现负数显然不成立
    S[i+16]-S[i]<=x-R[i]   // 当i<8时,由于昨天的雇人可以通宵上班,因此这个约束通过反面处理
    S[24] - S[0] >=x                     // 最后24小时内雇佣人应该大于等于x个人
    S[i]-S[j]<=K 则从顶点j向i引一条权值为K的边。该系统是否成立也就在于是否存在负环,于是用SPFA判断负环。
    然而x(也就是答案)未知,而x<=1000,所以可以二分查找找出最小的x。注意归零。
     
     
    要讲一下的就是这个s[i+16]-s[i]<=x-R[i]
    因为,我们的s[i]是表示1……i的人数和,那么要搞出s[i]-(昨天的)s[i-8],,,即s[i]-s[i+16],,但s[i]是第二天的
    所以s[i]+x-s[i+16]>=R[i]
    变形一下就成了s[i+16]-s[i]<=x-R[i]
     
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    const int maxn=30;
    
    int tu[maxn][maxn],cnt[maxn],go[maxn][maxn],vis[maxn],dis[maxn];
    int n,m,r[maxn],s[maxn];
    queue<int>Q;
    
    bool spfa(int x){
         memset(tu,0,sizeof(tu));
         memset(vis,0,sizeof(vis));
         memset(dis,0x3f,sizeof(vis));
         memset(cnt,0,sizeof(cnt));
         vis[24]=1;
         cnt[24]=1;
         dis[24]=0;
         Q.push(24);
         for (int i=1;i<=24;i++) tu[i-1][i]=s[i];
         for (int i=8;i<=24;i++) tu[i][i-8]=-r[i];
         for (int i=1;i<=7;i++) tu[i][i+16]=x-r[i];
         tu[24][0]=-x;
         while(!Q.empty()){
            int u=Q.front();
            Q.pop();
            vis[u]=false;
            for (int i=0;i<=24;i++){
                if(go[u][i]&&dis[i]>dis[u]+tu[u][i]){
                        dis[i]=dis[u]+tu[u][i];
                    if(!vis[i]){
                        Q.push(i);
                        cnt[i]++;
                        vis[i]=true;
                        if(cnt[i]>25) return false;
                    }
                }
            }
         }
         return true;
    }
    
    int main(){
        int t;
        scanf("%d",&t);
        for (int i=1;i<=24;i++) go[i][i-1]=go[i-1][i]=true;
        for (int i=8;i<=24;i++) go[i][i-8]=true;
        for (int i=1;i<=7;i++)  go[i][i+16]=true;
        go[24][0]=true;
        while(t--){
            memset(s,0,sizeof(s));
            int n;
            int x;
            for (int i=1;i<=24;i++) scanf("%d",&r[i]);
            scanf("%d",&n);
            for (int i=1;i<=n;i++) {
                    scanf("%d",&x);
                    s[x+1]++;
            }
            int l=1;
            int r=n;
            bool falg=false;
            int mid;
            while(l<=r){
                mid=(l+r)/2;
                if(spfa(mid)) {
                        r=mid-1;
                        falg=true;
                }
                else l=mid+1;
            }
            if(falg) printf("%d
    ",l);
            else printf("No Solution
    ");
        }
    return 0;
    }
  • 相关阅读:
    【Android-音乐类】音友 免费下载、试听、全网最全的音乐 还不快来白嫖~
    数据结构 10 基础数据结构 二叉堆 堆排序算法详解
    数据结构 9 基础数据结构 二叉堆 了解二叉堆的元素插入、删除、构建二叉堆的代码方式
    数据结构 8 基础排序算法详解、快速排序的实现、了解分治法
    Jenkins+tomcat自动发布的热部署/重启及遇到的坑解决办法
    Spring笔记(3)
    多线程高并发编程(12) -- 阻塞算法实现ArrayBlockingQueue源码分析
    多线程高并发编程(11) -- 非阻塞算法实现ConcurrentLinkedQueue源码分析
    多线程高并发编程(10) -- ConcurrentHashMap源码分析
    Spring笔记(1)
  • 原文地址:https://www.cnblogs.com/lmjer/p/9404061.html
Copyright © 2011-2022 走看看