zoukankan      html  css  js  c++  java
  • POJ 1275 Cashier Employment(差分约束)

    http://poj.org/problem?id=1275

    题意 : 一家24小时营业的超市,要雇出纳员,需要求出超市每天不同时段需要的出纳员数,午夜只需一小批,下午需要多些,希望雇最少的人,给出每小时需要的出纳员的最少数量,R(0),R(1),...,R(23)。R(0)表示从午夜到凌晨1:00所需要出纳员的最少数目;R(1)表示凌晨1:00到2:00之间需要的;以此类推。这些数据每一天都是相同的。有N人申请这工作,申请者 i ,从一个特定的时刻开始连续工作恰好8小时。定义ti(0<=ti<=23)为上面提到的开始时刻,也就是说,如果第i个申请者被录用,他)将从 ti 时刻开始连续工作8小时。

    思路 :差分约束,挺难的,看了好多人的题解,才稍微懂一些了,http://972169909-qq-com.iteye.com/blog/1185527,这个神写的不错,,,还有黑书上也有解释

    其实说的有点那啥,我一开始也还是没怎么看懂

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    
    using namespace std;
    
    const int INF = 9999999 ;
    struct node
    {
        int u,v,w ;
        int next ;
    } map[250] ;
    bool flag[25] ;
    int cnt,pre[25],cntt[25],dist[25] ;
    int r[25],t[26] ;
    
    void addedge(int u,int v,int w)
    {
        map[cnt].v = v ;
        map[cnt].w = w ;
        map[cnt].next = pre[u] ;
        pre[u] = cnt++ ;
    }
    
    void Init()
    {
        cnt = 0 ;
        memset(pre,-1,sizeof(pre)) ;
        memset(cntt,0,sizeof(cntt)) ;
        memset(flag,false,sizeof(flag)) ;
    }
    
    bool spfa(int start)
    {
        queue<int >Q ;
        for(int i = 0 ; i < 25 ; i++)
            dist[i] = -INF ;
        dist[start] = 0 ;
        Q.push(start) ;
        flag[start] = true ;
        while(!Q.empty())
        {
            int u = Q.front() ;
            Q.pop() ;
            if(++cntt[u] > 24)
                return false ;
            flag[u] = false ;
            for(int i = pre[u] ; i + 1 ; i = map[i].next)
            {
                int v = map[i].v ,w = map[i].w;
                if(dist[v] < dist[u] + w)
                {
                    dist[v] = dist[u] + w ;
                    if(!flag[v])
                    {
                        flag[v] = true ;
                        Q.push(v) ;
                    }
                }
            }
        }
        return true ;
    }
    int main()
    {
        int T ;
        scanf("%d",&T) ;
        while(T--)
        {
            for(int i = 1 ; i <= 24 ; i++)
                scanf("%d",&r[i]) ;
            int N ,s;
            scanf("%d",&N) ;
            memset(t,0,sizeof(t)) ;
            for(int i = 0 ; i < N ; i++)
            {
                scanf("%d",&s) ;
                t[s + 1]++ ;
            }
            int low = 0 ,high = N ;
            bool flagg = false ;
            while(low < high)
            {
                Init() ;
                int mid = (low+high)>>1 ;
                for(int i = 1 ; i <= 24 ; i++)
                {
                    addedge(i-1,i,0) ;
                    addedge(i,i-1,-t[i]) ;
                }
                for(int i = 8 ; i <= 24 ; i++)
                    addedge(i-8,i,r[i]) ;
                for(int i = 1 ; i <= 7 ; i++)
                    addedge(i+16,i,r[i]-mid) ;
                addedge(0,24,mid) ;
                if(spfa(0))
                {
                    high = mid ;
                    flagg = true ;
                }
                else low = mid+1 ;
            }
            if(flagg)
                printf("%d
    ",high) ;
            else printf("No Solution
    ") ;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    hdoj 2803 The MAX【简单规律题】
    hdoj 2579 Dating with girls(2)【三重数组标记去重】
    hdoj 1495 非常可乐【bfs隐式图】
    poj 1149 PIGS【最大流经典建图】
    poj 3281 Dining【拆点网络流】
    hdoj 3572 Task Schedule【建立超级源点超级汇点】
    hdoj 1532 Drainage Ditches【最大流模板题】
    poj 1459 Power Network【建立超级源点,超级汇点】
    hdoj 3861 The King’s Problem【强连通缩点建图&&最小路径覆盖】
    hdoj 1012 u Calculate e
  • 原文地址:https://www.cnblogs.com/luyingfeng/p/3542425.html
Copyright © 2011-2022 走看看