【POJ1275】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 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

题意:

  德黑兰的一家每天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)更多的出纳员在工作。

分析:

  因为一开始就知道这是一道差分约束题,于是就往这方面想了。然而可爱的是,还是没有想出来。TAT~

  其实就是不会搞循环的情况,感觉我的不等式这样子就有三个元了TAT。我们设xi为我们选择了xi个在i时间开始工作的员工,先不考虑循环的情况,那么对于时间点i,那么在时间点i这个时刻正在工作的人数为x[i-7]+x[i-6]+...x[i],用sum数组维护x,即为sum[i]-sum[i-8]。于是我们得到不等式sum[i]-sum[i-8]>=need[i]。(need[i]为题目输入的时间点i需要的员工数)

  循环的情况怎么搞呢?对于i(i<=7),那么后面某一段时间开始工作的员工也会影响答案,那么我们得到的不等式就是sum[24]-sum[i+16]+sum[i]>=need[i](这里的时间点我从1~24考虑)。这里有三个未知数啊,怎么办呢,于是我想了很久没有想出来。

  竟然是!!二分枚举一下sum[24]就好了,那么就把sum[24]看成常数把!!看到这里,我哭了,世界上竟有如此低智商的我!!

  好吧...因为如果我们雇x个人可以搞定全部,那么雇多一点人也可以的嘛,这就是某种单调性,于是我们可以二分。最后再连一条24->0的边权为-sum[24]就可以了。

  差分约束...

  对了,还有一些隐性条件,千万不要漏,上一题中已经说过了。

  eg. x[i]-x[i-1]>=0

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 #include<queue>
  8 #define Maxn 30
  9
 10 int a[Maxn],sum[Maxn];
 11 int first[Maxn],dis[Maxn],cnt[Maxn];
 12 bool inq[Maxn];
 13
 14 struct node
 15 {
 16     int x,y,c,next;
 17 }t[Maxn*4];int len;
 18
 19 void ins(int x,int y,int c)
 20 {
 21     t[++len].x=x;t[len].y=y;t[len].c=c;
 22     t[len].next=first[x];first[x]=len;
 23 }
 24
 25
 26 queue<int > q;
 27 bool spfa(int s)
 28 {
 29     while(!q.empty()) q.pop();
 30     memset(dis,63,sizeof(dis));
 31     memset(inq,0,sizeof(inq));
 32     memset(cnt,0,sizeof(cnt));
 33     dis[s]=0;inq[s]=1;q.push(s);
 34     while(!q.empty())
 35     {
 36         int x=q.front();q.pop();inq[x]=0;
 37         for(int i=first[x];i;i=t[i].next)
 38         {
 39             int y=t[i].y;
 40             if(dis[y]>dis[x]+t[i].c)
 41             {
 42                 dis[y]=dis[x]+t[i].c;
 43                 if(!inq[y])
 44                 {
 45                     q.push(y);
 46                     inq[y]=1;
 47                     if(++cnt[y]>25) return 0;
 48                 }
 49             }
 50         }
 51     }
 52     return 1;
 53 }
 54
 55 bool check(int x)
 56 {
 57     for(int i=1;i<=7;i++) t[len-8+i].c=x-a[i];
 58     t[len].c=-x;
 59     return spfa(0);
 60 }
 61
 62 void ffind(int l,int r)
 63 {
 64     //check(1);
 65     while(l<r)
 66     {
 67         int mid=(l+r)>>1;
 68         if(check(mid)) r=mid;
 69         else l=mid+1;
 70     }
 71     printf("%d\n",l);
 72 }
 73
 74 int main()
 75 {
 76     int T;
 77     scanf("%d",&T);
 78     while(T--)
 79     {
 80         int x,n;
 81         memset(sum,0,sizeof(sum));
 82         for(int i=1;i<=24;i++) scanf("%d",&a[i]);
 83         scanf("%d",&n);
 84         for(int i=1;i<=n;i++)
 85         {
 86             int x;
 87             scanf("%d",&x);
 88             sum[x+1]++;
 89         }
 90         len=0;
 91         memset(first,0,sizeof(first));
 92         for(int i=1;i<=24;i++) ins(i-1,i,sum[i]);
 93         for(int i=1;i<=24;i++) ins(i,i-1,0);
 94         for(int i=8;i<=24;i++) ins(i,i-8,-a[i]);
 95         for(int i=1;i<=7;i++) ins(i,16+i,0);
 96         ins(24,0,0);
 97         if(!check(n)) {printf("No Solution\n");continue;}
 98         ffind(0,n);
 99     }
100     return 0;
101 }

[poj1275]

2016-04-12 13:51:47

时间: 2024-11-09 00:39:51

【POJ1275】Cashier Employment的相关文章

【HDOJ】1158 Employment Planning

简单DP. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <climits> 5 #define MAXN 105 6 7 int dp[15][MAXN]; 8 int a[15]; 9 10 int getMin(int a, int b) { 11 return a<b?a:b; 12 } 13 14 int main() { 15 int n,

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

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

图论常用算法之一 POJ图论题集【转载】

POJ图论分类[转] 一个很不错的图论分类,非常感谢原版的作者!!!在这里分享给大家,爱好图论的ACMer不寂寞了... (很抱歉没有找到此题集整理的原创作者,感谢知情的朋友给个原创链接) POJ:http://poj.org/ 1062* 昂贵的聘礼 枚举等级限制+dijkstra 1087* A Plug for UNIX 2分匹配 1094 Sorting It All Out floyd 或 拓扑 1112* Team Them Up! 2分图染色+DP 1125 Stockbroker

【转载】夜深人静写算法(四)——差分约束

[转载]夜深人静写算法(四) - 差分约束  目录     一.引例       1.一类不等式组的解   二.最短路       1.Dijkstra       2.图的存储       3.链式前向星       4.Dijkstra + 优先队列       5.Bellman-Ford       6.SPFA       7.Floyd-Warshall   三.差分约束        1.数形结合        2.三角不等式        3.解的存在性        4.最大值

【HDOJ图论题集】【转】

1 =============================以下是最小生成树+并查集====================================== 2 [HDU] 3 1213 How Many Tables 基础并查集★ 4 1272 小希的迷宫 基础并查集★ 5 1325&&poj1308 Is It A Tree? 基础并查集★ 6 1856 More is better 基础并查集★ 7 1102 Constructing Roads 基础最小生成树★ 8 1232

【NOI2004】郁闷的出纳员Codevs1286

题目描述 Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情. 工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气

【Kettle】4、SQL SERVER到SQL SERVER数据转换抽取实例

1.系统版本信息 System:Windows旗舰版 Service Pack1 Kettle版本:6.1.0.1-196 JDK版本:1.8.0_72 2.连接数据库 本次实例连接数据库时使用全局变量. 2.1 创建新转换:spoon启动后,点击Ctrl+N创建新转换 2.2 在新转换界面中,右键点击DB连接,系统会弹出[数据库连接]界面. windows系统环境下,可用${}获取变量的内容. 说明: 连接名称:配置数据源使用名称.(必填) 主机名称:数据库主机IP地址,此处演示使用本地IP(

详解go语言的array和slice 【二】

上一篇  详解go语言的array和slice [一]已经讲解过,array和slice的一些基本用法,使用array和slice时需要注意的地方,特别是slice需要注意的地方比较多.上一篇的最后讲解到创建新的slice时使用第三个索引来限制slice的容量,在操作新slice时,如果新slice的容量大于长度时,添加新元素依然后使源的相应元素改变.这一篇里我会讲解到如何避免这些问题,以及迭代.和做为方法参数方面的知识点. slice的长度和容量设置为同一个值 如果在创建新的slice时我们把