poj1275--Cashier Employment(差分约束)

poj1275:题目链接

题目大意:给出24个数,第i个数表示在(i,i+1)小时内需要的人数,之后m个数,代表m个人前来应聘,其中每个人工作连续的8小时,给出应聘的人开始工作的时间,问最少需要雇佣的人数(可以在某个时间段中人数多于需要的人数)

差分约束:

1、题目需要求什么,就找什么之间的关系(二项式),比如,题目求雇佣的人数,就找出雇佣人数之间的关系,s[i]代表从0到i一共雇佣的人数

2、注意0的问题,和总和的问题。

3、判断的问题,不能存在环,和不能违背要求的值

又因为题中雇佣人数会形成一个环,所以可以虚拟一个节点k,代表最初的节点 s[k] = 0

那么归结关系有

s[i]:0到i时刻雇佣的总人数,h[i]:i时刻;来应聘的人数,r[i]:i时刻需要的人数

设:需要的人数为sum

s[i] - s[i-1] >= 0

s[i] - s[i-1] <= h[i] ;

总数:s[23] - s[k] >= sum

s[i] - s[i-8] >= r[i] (i >= 8)

sum - s[i+16] + s[i] >= r[i] (i < 8)

对上面的条件整理,然后求最长路,得到最小的一个结果

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std ;
#define INF 0x3f3f3f3f
struct node{
    int v , w ;
    int next ;
}edge[1000];
int head[50] , cnt ;
int r[30] , h[30] ;
int dis[30] , vis[30] ;
void add(int u,int v,int w) {
    edge[cnt].v = v ; edge[cnt].w = w ;
    edge[cnt].next = head[u] ; head[u] = cnt++ ;
}
int spfa(int sum) {
    memset(vis,0,sizeof(vis)) ;
    memset(dis,-INF,sizeof(dis)) ;
    int u , v , i , num = 0 ;
    queue <int> que ;
    while( !que.empty() ) que.pop() ;
    vis[24] = 1 ;
    dis[24] = 0 ;
    que.push(24) ;
    while( !que.empty() ) {
        u = que.front() ;
        que.pop() ;
        vis[u] = 0 ;
        for(i = head[u] ; i != -1 ; i = edge[i].next) {
            v = edge[i].v ;
            if( dis[v] < dis[u] + edge[i].w ) {
                dis[v] = dis[u] + edge[i].w ;
                num++ ;
                if( vis[v] == 0 ) {
                    que.push(v) ;
                    vis[v] = 1 ;
                }
            }
        }
        if( num > 1000 ) return 0 ;
    }
    if( dis[23] == sum ) return 1 ;
    return 0 ;
}
int solve(int sum) {
    memset(head,-1,sizeof(head)) ;
    cnt = 0 ;
    int i , j ;
    add(24,0,0) ;
    add(0,24,-h[0]) ;
    add(24,23,sum) ;
    for(i = 1 ; i <= 23 ; i++) {
        add(i-1,i,0) ;
        add(i,i-1,-h[i]) ;
    }
    for(i = 0 ; i <= 23 ; i++) {
        if( i >= 8 )
            add(i-8,i,r[i]) ;
        else
            add(i+16,i,r[i]-sum) ;
    }
    if( spfa(sum) ) return 1 ;
    return 0 ;
}
int main() {
    int t , i , j , m ;
    scanf("%d", &t) ;
    while( t-- ) {
        memset(h,0,sizeof(h)) ;
        for(i = 0 ; i <= 23 ; i++)
            scanf("%d", &r[i]) ;
        scanf("%d", &m) ;
        for(i = 0 ; i < m ; i++){
            scanf("%d", &j) ;
            h[j]++ ;
        }
        for(i = 0 ; i <= m ; i++)
            if( solve(i) )
                break ;
        if( i <= m )
            printf("%d\n", i ) ;
        else
            printf("No Solution\n") ;
    }
    return 0 ;
}
时间: 2024-10-28 21:18:35

poj1275--Cashier Employment(差分约束)的相关文章

POJ1275/ZOJ1420/HDU1529 Cashier Employment (差分约束)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 题意:一商店二十四小时营业,但每个时间段需求的出纳员不同,现有n个人申请这份工作,其可以从固定时间t连续工作八个小时,问在满足需求的情况下最小需要多少个出纳 一道十分经典的差分约束题目,在构图上稍有难度 为避免负数,时间计数1-24. 令: r[i]表示i时间需要的人数 (1<=i<=24) num[i]表示i时间应聘的人数 (1<=i<=24) x[i]表示i时间

POJ1275 Cashier Employment[差分约束系统 || 单纯形法]

Cashier Employment Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7997   Accepted: 3054 Description A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hir

poj 1275 Cashier Employment 差分约束

差分约束模板题,差分约束是判断联立不等式组是否有解的一种方法,建图是关键. 代码: //poj 1275 //sep9 #include <iostream> #include <queue> using namespace std; const int maxM=10024; const int maxN=32; struct Edge { int v,w,nxt; }edge[maxM]; int t[maxN],c[maxN],head[maxN],vis[maxN],inq

HDU.1529.Cashier Employment(差分约束 最长路SPFA)

题目链接 \(Description\) 给定一天24h 每小时需要的员工数量Ri,有n个员工,已知每个员工开始工作的时间ti(ti∈[0,23]),每个员工会连续工作8h. 问能否满足一天的需求.若能,输出最少需要多少员工. \(Solution\) 参考. 既然给的是开始工作时间,那么就先根据开始时间做 设Ai表示在i时开始工作的人数(未知),Bi表示i时可工作人数的上限(已知) 那么有:(注意可以跨天) A[i-7]+A[i-6]+...+A[i-1]+A[i] >= R[i] (7 <

poj 1275 Cashier Employment - 差分约束 - 二分答案

A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hired you to help him, solve his problem. The problem is that the supermarket needs different number of cashiers at d

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] -

POJ1275 Cashier Employment 【二分 + 差分约束】

题目链接 POJ1275 题解 显然可以差分约束 我们记\(W[i]\)为\(i\)时刻可以开始工作的人数 令\(s[i]\)为前\(i\)个时刻开始工作的人数的前缀和 每个时刻的要求\(r[i]\),可以通过如下限制满足: \[s[i] - s[i - 8] \ge r[i]\] \[0 \le s[i] - s[i - 1] \le W[i]\] 但是\(i - 8\)可能为负,回到上一天的时刻,导致区间不连续,不好处理 我们可以二分答案\(sum\) 将\(i < 8\)的部分改为: \[

poj——1275 Cashier Employment 差分约束系统

Cashier Employment Description A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hired you to help him, solve his problem. The problem is that the supermarket needs di

差分约束小结

ZOJ 2770 Burn the Linked Camp /* ZOJ 2770 Burn the Linked Camp 差分约束 */ #include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; const int MAXN = 1009; struct Edge { int v, ne, c; } G[MAXN*MAXN]

Cashier Employment(poj1275

Cashier Employment Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9205   Accepted: 3564 Description A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hir