1755 【差分约束】Cashier Employment(出纳员的雇佣)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
【差分约束】Cashier Employment(出纳员的雇佣)
Time Limit:1000MS Memory Limit:65536K
Total Submit:2 Accepted:2
Description
出纳员的雇佣(cashier.pas/c/cpp)
【问题描述】
Tehran的一家每天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)更多的出纳员在工作。
Input
第一行为测试点个数(<= 20)。每组测试数据的第一行为24个整数表示R(0),R(1),...,
R(23)(R(I)<= 1000)。接下来一行是N,表示申请者数目(0 <= N <= 1000),接下来每行包含一个整数tI (0 <= tI <= 23)。两组测试数据之间没有空行。Output
对于每个测试点,输出只有一行,包含一个整数,表示需要出纳员的最少数目。如果无解,你应当输出“No Solution”。
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
23
22
1
10
Sample Output
1
Hint
本题数据不完整,请在本系统测试通过后到/problem?id=1275 提交完整测试!
Source
Tehran 2000
解析1:
题意: 一家24小时营业的超市,需要一批出纳员来满足它的需求,该超市在每天的不同时刻需要不同数目的出纳员来为顾客提供服务,现在给出一天里每一小时需要出纳员的最少数量……r[0],r[1],……r[23].r[0]表示从午夜到上午1:00需要出纳员的最少数目等等,每一天这些数据都是相同的,有n个人申请这项工作,每个申请者i在每天24小时中,从某一个特定的时刻开始连续工作恰好8小时,定义t[i(0<=t[i]<=23)为上面提到的开始时刻,也就是说,如果第i个申请者被录用,他将从t[i]时刻开始连续工作8小时.输入r[i]和t[i],计算为满足上述限制需要雇佣的最少出纳员数目.注意在每一时刻可以有比对应的r[i]更多的出纳员在工作.
r[0……23]……每个时刻需要的出纳员数目
t[0……23]……每个时刻应征的申请者数目
求s[0……23]……s[i]表示0……i时刻雇佣的出纳员总数,s[i]-s[i-1]就是i时刻录用的出纳员数目,设s[-1]=0,sum为雇佣的所有出纳员总数,那么一个可行方案应该满足: s[i]-s[i-1]>=0 即在i时刻录用的出纳员数目大于或等于0
s[i]-s[i-1]<=t[i] 即在i时刻录用的出纳员数目应该小于在i时刻申请者数目
s[23]-s[-1]>=sum
s[i]-s[j]>=r[i] 此时i>j&&i=(j+8)%24 因为在0……j时刻雇佣的出纳员连续工作8个小时,此时i=j+8很显然需要重新雇佣出纳员且最小为r[i]
s[j]-s[i]<=sum-r[i] 此时i
作8个小时后到了下一天的i时刻,所以从i……j=16+i时刻需要雇佣的出纳员数目最大为sum-r[i]
由于sum是未知的,所以可以根据上述约束条件来构造约束图,为方便建图,以0为起点,由于题目要求的是出纳员的最少数目,所以建图后用Bellman_Ford算法求解单源最长路,在这过程中枚举sum,如果途中不存在环且s[24]=sum,那么就找到了一个可行解.
将约束条件整理如下:
s[i]-s[i-1]>=0
s[i-1]-s[i]>= -t[i] i=(1,2 (24)
s[24]-s[0]>=sum
s[i]-s[j]>=r[i] i>j i=(j-1+8)%24+1
s[i]-s[j]>=r[i]-sum i Bellman_Ford算法求解最长路,在主程序中枚举sum,就可以得到需要雇佣的出纳员数目的最小值,也可以二分法求解. 解析2: 设num[ i ]为i时刻能够开始工作的人数,x[ i ]为实际雇佣的人数,设r[ i ]为i 时刻至少需要工作的人数,s[ I ]=x[ 1 ]+x[ 2 ]…+x[ I ] 有如下关系: x[ I ]<=num[ I ] x[ I-7 ]+x[ I-6 ]+x[ I-5 ]+x[ I-4 ]+x[ I-3 ]+x[ I-2 ]+x[ I-1 ]+x[ I ]>=r[ I ] 0<=s[ I ]-s[ I-1 ]<=num[ I ],1<=I<=24 s[I]-s[ I-8 ]>=r[ I ], 8<=I<=24 s[ I ]-s[ I+16 ]>=r[ I ]-sum,1<=I<=7 s[0]=0 s[24]-s[0]>=sum(冯威的论文少了这个条件,看了别人的解题报告,才发现。想想也是,sum是枚举的当前最小值,s[24]是实际工作的工人,那么其一定大于sum) 解析3: 用s[i]表示从0时刻到i时刻雇的人的总数,t[i]是在i时刻来应聘的人,ans 为这一天雇佣的总人数,s[-1]=0,很容易得到两个约束: 在i时刻的雇佣的人一定之能少于等于t[i],而且一定大于等于0(只是大于等于0,而不能说大于等于R[i] ,因为前面的时刻的人可以流下来到i时刻继续工作)。就是一个人也不雇.