1755 【差分约束】Cashier Employment(出纳员的雇佣)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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] 此时ii说明可能某一天雇佣的出纳员连续工

作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时刻继续工作)。就是一个人也不雇.

相关文档
最新文档