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 different times of each day (for example, a few cashiers after midnight, and many in the afternoon) to provide good service to its customers, and he wants to hire the least number of cashiers for this job.

The manager has provided you with the least number of cashiers needed for every one-hour slot of the day. This data is given as R(0), R(1), ..., R(23): R(0) represents the least number of cashiers needed from midnight to 1:00 A.M., R(1) shows this number for duration of 1:00 A.M. to 2:00 A.M., and so on. Note that these numbers are the same every day. There are N qualified applicants for this job. Each applicant i works non-stop once each 24 hours in a shift of exactly 8 hours starting from a specified hour, say ti (0 <= ti <= 23), exactly from the start of the hour mentioned. That is, if the ith applicant is hired, he/she will work starting from ti o‘clock sharp for 8 hours. Cashiers do not replace one another and work exactly as scheduled, and there are enough cash registers and counters for those who are hired.

You are to write a program to read the R(i) ‘s for i=0..23 and ti ‘s for i=1..N that are all, non-negative integer numbers and compute the least number of cashiers needed to be employed to meet the mentioned constraints. Note that there can be more cashiers than the least number needed for a specific slot.


Input

The first line of input is the number of test cases for this problem (at most 20). Each test case starts with 24 integer numbers representing the R(0), R(1), ..., R(23) in one line (R(i) can be at most 1000). Then there is N, number of applicants in another line (0 <= N <= 1000), after which come N lines each containing one ti (0 <= ti <= 23). There are no blank lines between test cases.


Output

For each test case, the output should be written in one line, which is the least number of cashiers needed. 
If there is no solution for the test case, you should write No Solution for that case.


Sample Input

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

Sample Output

1

题目大意

  一个超市在第$i$小时中工作的员工数目不能少于$req[i]$个。有$n$个应聘的人,第$i$个人愿意从$t_{i}$开始工作8小时,问最少需要聘请多少人才能使得达到要求。

  设$x_{i}$表示第$i$个小时中开始工作的员工数目。为了表示八个小时内的员工数目,定义$s_{i} = x_{0} + \cdots + x_{i - 1}$。用$own[i]$表示愿意从时刻$i$开始工作的人数

  于是便有如下一些不等式:

  • $0 \leqslant s_{i} - s_{i - 1} \leqslant own[i - 1]$
  • $\left\{\begin{matrix}s_{i} - s_{i - 8}\geqslant req[i - 1]\ \ \ \ \ \ \ \ \ \ \left ( i \geqslant 8 \right ) \\ s_{16 + i} - s_{i}\leqslant s_{24} - req[i - 1]\ \left ( i \leqslant 8 \right )\end{matrix}\right.$

  但是发现第二个不等式组中的第二个不等式含有3个未知量,即$s_{24}$,但是总共就只有这么一个,可以考虑枚举它。

  显然答案满足二分性质,所以二分它,增加限制$s_{24} = mid$。

Code

 1 /**
 2  * poj
 3  * Problem#1275
 4  * Accepted
 5  * Time: 16ms
 6  * Memory: 672k
 7  */
 8 #include <iostream>
 9 #include <cstring>
10 #include <cstdio>
11 #include <queue>
12 using namespace std;
13 typedef bool boolean;
14
15 const int N = 26;
16
17 int T;
18 int n;
19 int req[N], own[N];
20 int g[N][N];
21 int f[N];
22 int lab[N];
23 boolean vis[N];
24
25 inline void init() {
26     for (int i = 0; i < 24; i++)
27         scanf("%d", req + i);
28     scanf("%d", &n);
29     memset(own, 0, sizeof(own));
30     for (int i = 1, x; i <= n; i++) {
31         scanf("%d", &x);
32         own[x]++;
33     }
34 }
35
36 queue<int> que;
37 inline boolean check(int mid) {
38     for (int i = 1; i < 8; i++)
39         g[16 + i][i] = req[i - 1] - mid;
40     g[0][24] = mid;
41     g[24][0] = -mid;
42     fill(f, f + 25, -2333);
43     memset(lab, 0,    sizeof(lab));
44     que.push(0);
45     f[0] = 0;
46     while (!que.empty()) {
47         int e = que.front();
48         que.pop();
49         vis[e] = false;
50         if (++lab[e] >= 25)    return false;
51         for (int i = 0; i < 25; i++)
52             if (g[e][i] >= -1000 && f[e] + g[e][i] > f[i]) {
53                 f[i] = f[e] + g[e][i];
54                 if (!vis[i]) {
55                     que.push(i);
56                     vis[i] = true;
57                 }
58             }
59     }
60 //    for (int i = 0; i <= 24; i++)
61 //        cerr << f[i] << " ";
62 //    cerr << endl;
63     return true;
64 }
65
66 inline void solve() {
67     memset(g, 0x80, sizeof(g));
68     for (int i = 0; i < 24; i++)
69         g[i][i + 1] = 0, g[i + 1][i] = -own[i];
70     for (int i = 8; i <= 24; i++)
71         g[i - 8][i] = req[i - 1];
72     int l = 0, r = n;
73     while (l <= r) {
74         int mid = (l + r) >> 1;
75         if (check(mid))
76             r = mid - 1;
77         else
78             l = mid + 1;
79     }
80     if (r == n)
81         puts("No Solution");
82     else
83         printf("%d\n", r + 1);
84 }
85
86 int main() {
87     scanf("%d", &T);
88     while(T--) {
89         init();
90         solve();
91     }
92     return 0;
93 }

原文地址:https://www.cnblogs.com/yyf0309/p/8450052.html

时间: 2025-01-09 10:31:46

poj 1275 Cashier Employment - 差分约束 - 二分答案的相关文章

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

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

图论(差分约束系统):POJ 1275 Cashier Employment

Cashier Employment Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7651   Accepted: 2886 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

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时间

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 <

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

HDU [1529] || POJ [P1275] Cashier Employment

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

poj 3169 Layout(差分约束)

Layout Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6549   Accepted: 3168 Description Like everyone else, cows like to stand close to their friends when queuing for feed. FJ has N (2 <= N <= 1,000) cows numbered 1..N standing along a

POJ 2018 Best Cow Fences(二分答案)

POJ 2018 Best Cow Fences(二分答案) Best Cow Fences Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 12144 Accepted: 3958 Description Farmer John's farm consists of a long row of N (1 <= N <= >100,000)fields. Each field contains a certain nu