Cashier Employment

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1214    Accepted Submission(s): 537

Problem 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
 
Source
 

较为难的差分约束系统。
首先我们要确定我们要求解的东西,才能依次建立不等式。
显然我们要求解第0-23小时每个小时加入的人手的和。
对于求解的答案,我们设立 $c[i]=\sum_{j=0}^{i-1} x[j]( 1 \leq i \leq 24)$,其中 $x[j]$是j这个时刻实际开始工作的人数。并且$c[0]=0$,且只有c[0]为已知,其他为未知。
那么我们要求解的就是c[24]的最小值。
同样我们也设立$A[i]=\sum_{j=0}^{i-1} num[j]( 1 \leq i \leq 24)$,其中 $num[j]$是j这个时刻开始工作人数的最大值。并且$A[0]=0$。
还有$R[i]$表示i~i+1这短时间要有多少人工作。
那我们可以轻易地得出下面的不等式:
$(1\leq i \leq 8)$:
$ c[i]-c[0]+c[24]-c[16+i] \leq R[i-1] $,其中-c[0]可以去掉。
$(9\leq i \leq 24)$:
$ c[i]-c[i-8] \leq R[i-1] $
当然对于所有的$(1\leq i \leq 24)$:
$ c[i]-c[i-1] \leq x[i-1] $
$ c[i]-c[i-1] \geq 0 $
除了第一个1~8的不等式,我们都可以直接转化为最短路(最长路)用spfa求解。
对于第一个不等式 我们不能利用类似于$c[24]-c[16+i] \leq A[24]-A[16+i] $这样的不等式条件去进行加减变换,因为这会改变约束条件使得答案不正确。
同时 $c[24]-c[16+i] \leq A[24]-A[16+i] $ 已经改变了初始的约束条件。
所以我们只能去先确定其中一个未知数的值,然后spfa一遍看他符不符合这些不等式的情况,符合则该未知数的值即为该未知数的是解之一。那么我选择确定c[24],因为他正好是我们要求的答案ans。
因此我们可以二分查找最小的ans,也可以0~n枚举一遍ans,n=A[24]。
当然我们既然确定了ans,那么我们第一个不等式就变成了:
$ c[i]-c[16+i] \leq R[i-1]-ans $
还要加入约束条件
$ c[24]-c[0] \leq ans $ 这个约束条件即为ans确定的不等式表达。
 
 #include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#define INF 1000000000
#define clr(x) memset(x,0,sizeof(x))
#define clr_1(x) memset(x,-1,sizeof(x))
#define clrmax(x) memset(x,0x3f3f3f3f,sizeof(x))
#define clrmin(x) memset(x,-0x3f3f3f3f,sizeof(x))
using namespace std;
struct node
{
int to,val,next;
}edge[*];
queue<int> Q;
int head[];
int dis[];
int R[];
int in[],inf[];
int x[];
int c[];
int n,cnt,l,r,k,ans;
void addedge(int l,int r,int k);
bool spfa(int s);
void init();
int min(int a,int b)
{
return a<b?a:b;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
clr(x);
while(!Q.empty())
Q.pop();
for(int i=;i<=;i++)
scanf("%d",&R[i]);
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&l);
x[l]++;
}
c[]=;
for(int i=;i<=;i++)
{
c[i]=c[i-]+x[i-];
}
ans=-;
for(int kase=;kase<=n;kase++)
{
init();
for(int i=;i<=;i++)
addedge(+i,i,R[i-]-kase);
for(int i=;i<=;i++)
addedge(i-,i,R[i-]);
for(int i=;i<=;i++)
{
addedge(i,i-,-x[i-]);
addedge(i-,i,);
}
addedge(,,kase);
if(spfa())
{
ans=kase;
break;
}
}
if(ans==-)
printf("No Solution\n");
else
printf("%d\n",ans);
}
return ;
}
void addedge(int l,int r,int k)
{
edge[++cnt].to=r;
edge[cnt].val=k;
edge[cnt].next=head[l];
head[l]=cnt;
return;
}
bool spfa(int s)
{
dis[s]=;
Q.push(s);
inf[s]=;
in[s]=;
int v,k;
while(!Q.empty())
{
v=Q.front();
Q.pop();
inf[v]=;
k=head[v];
while(k!=-)
{
if(dis[v]+edge[k].val>dis[edge[k].to])
{
dis[edge[k].to]=dis[v]+edge[k].val;
if(!inf[edge[k].to])
{
if(++in[edge[k].to]>)
return false;
inf[edge[k].to]=;
Q.push(edge[k].to);
}
}
k=edge[k].next;
}
}
return true;
}
void init()
{
clr(inf);
clr_1(head);
clrmin(dis);
clr(in);
cnt=;
return ;
}

hdu 1529 Cashier Employment(差分约束)的更多相关文章

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

    题目链接 \(Description\) 给定一天24h 每小时需要的员工数量Ri,有n个员工,已知每个员工开始工作的时间ti(ti∈[0,23]),每个员工会连续工作8h. 问能否满足一天的需求.若 ...

  2. [HDU 1529]Cashier Employment(差分约束系统)

    [HDU 1529]Cashier Employment(差分约束系统) 题面 有一个超市,在24小时对员工都有一定需求量,表示为\(r_i\),意思为在i这个时间至少要有i个员工,现在有n个员工来应 ...

  3. 【POJ1275】Cashier Employment 差分约束

    [POJ1275]Cashier Employment 题意: 超市经历已经提供一天里每一小时需要出纳员的最少数量————R(0),R(1),...,R(23).R(0)表示从午夜到凌晨1:00所需要 ...

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

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 题意:一商店二十四小时营业,但每个时间段需求的出纳员不同,现有n个人申请这份工作, ...

  5. hdu1529 Cashier Employment[差分约束+二分答案]

    这题是一个类似于区间选点,但是有一些不等式有三个未知量参与的情况. 依题意,套路性的,将小时数向右平移1个单位后,设$f_i$为前$i$小时工作的人数最少是多少,$f_{24}$即为所求.设$c_i$ ...

  6. Cashier Employment 差分约束

    题意:有一个超市需要一些出纳员,已给出这个超市在各个时间段(0-1,1-2,2-3...共24个时间段)至少需要的出纳员数目,现在前来应聘有n个人,每个人都有一个固定的开始工作的时间,这也意味着从这个 ...

  7. POJ1275 Cashier Employment(差分约束)

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9078   Accepted: 3515 Description A sup ...

  8. 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 n ...

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

    Cashier Employment Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7997   Accepted: 305 ...

随机推荐

  1. js 作用域链&内存回收&变量&闭包

    闭包主要涉及到js的几个其他的特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等 一.作用域链:函数在定义的时候创建的,用于寻找使用到的变量的值的一个索引,而他内部的规则是,把函数自身的本地变量放在 ...

  2. ButterKnife用法详解

    http://www.cnblogs.com/zhaoyanjun/p/6016341.html 本文出自[赵彦军的博客] 前言 ButterKnife 简介 ButterKnife是一个专注于And ...

  3. Sberbank Russian Housing Market比赛总结

    第一次真正意义上参加kaggle比赛,都是工作之余看看别人的kernel,然后整理整理自己的分析代码. 总体来说,本次比赛对我而言更像一个入门比赛,更多的是走走kaggle比赛的整个流程,看看高手们都 ...

  4. TCP之listen&backlog

    1. listen函数: #include <sys/socket.h> int listen(int sockfd, int backlog); ret-成功返回0 失败返回- list ...

  5. quazip 在windows msvc 2005 下的编译

    quazip 在windows  msvc 2005 下的编译 http://blog.csdn.net/v6543210/article/details/11661427

  6. gunicorn 启动无日志

    gunicorn -c gunicorn_info.py info:app 接手整理老项目,发现有个服务迁移后启动不了,也没报错信息 修改gunicorn_info.py里的daemon = not ...

  7. sense之间的数据传输

    下面介绍一种原界面向目标界面传值 和 两种 由目标界面返回值给原界面的方法 界面解释: a界面和b界面都在导航控制器中, a界面触发时间跳转至b界面,b界面上设定完毕数据后返回a界面 a界面:原界面 ...

  8. Leetcode 之Balanced Binary Tree(49)

    用递归的方式来做,左右两棵子树的高度差不超过1.分成两部分,一部分递归得到树的高度,一部分递归检查左右子树是否是平衡二叉树. int getHeight(TreeNode *root) { ; ; } ...

  9. redis的安装和php的redis扩展

    一.redis的安装和配置 1.官方现在源码 https://redis.io/download 2.解压源码 tar  zxvf   redis-3.2.11.tar.gz 3.编译 make 编译 ...

  10. 14:django 用户认证系统

    django认证系统包含三个部分:用户.权限和分组 安装 django项目默认启用了认证系统,如果不是使用django-admin.py创建项目的可以通过在settings配置文件里面的INSTALL ...