POJ1275 Cashier Employment
Cashier Employment
给出24个数,第i个数表示在(i,i+1)小时内需要的人数,之后m个数,代表m个人前来应聘,其中每个人工作连续的8小时,给出应聘的人开始工作的时间,问最少需要雇佣的人数(可以在某个时间段中人数多于需要的人数)
题解
参照刀刀狗0102的题解。
问题分析:因为二十四小时是循环的,所以这是一个环,这题不能只用前缀和表示关系。解决办法是枚举(二分)答案,然后连特殊边(边权根据枚举的答案变化)解决问题。
差分约束:
- 题目需要求什么,就找什么之间的关系(二项式),比如,题目求雇佣的人数,就找出雇佣人数之间的关系,s[i]代表从0到i一共雇佣的人数
- 注意0的问题,和总和的问题。
- 判断的问题,不能存在环,和不能违背要求的值
那么归结关系有
s[i]:1到i时刻雇佣的总人数。
c[i]:i时刻;来应聘的人数。
r[i]:i时刻需要的人数。
设需要的人数为sum,即枚举的答案。
- 实际问题
0 <= s[i] - s[i-1] <= h[i] ; - 总数
s[24] - s[0] >= sum - 分类讨论约束
s[i] - s[i-8] >= r[i] (i >= 8)
sum - s[i+16] + s[i] >= r[i] (i < 8)
对上面的条件整理,然后求最短路,如果没有负环那么就有解。
#include<iostream>
#include<cstring>
#include<queue>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std;
co int N=1e3+1;
int n,r[N],c[N],d[N],s[N];
int head[N],edge[N],next[N],leng[N],tot;
bool v[N];
il void add(int x,int y,int z){
edge[++tot]=y,leng[tot]=z,next[tot]=head[x],head[x]=tot;
}
int spfa(int now){
for(int i=1;i<=7;++i) leng[head[i]]=now-r[i];
leng[head[24]]=-now;
memset(d,0x3f,sizeof d);
memset(s,0,sizeof s);
queue<int> q;
for(int i=0;i<=24;++i) q.push(i),d[i]=0,v[i]=1;
while(q.size()){
int x=q.front();q.pop();
v[x]=0;
for(int i=head[x];i;i=next[i]){
int y=edge[i],z=leng[i];
if(d[y]>d[x]+z){
d[y]=d[x]+z,s[y]=s[x]+1;
if(s[y]>25) return 0;
if(!v[y]) q.push(y),v[y]=1;
}
}
}
return 1;
}
void Cashier_Employment(){
for(int i=1;i<=24;++i) read(r[i]);
read(n),memset(c,0,sizeof c);
for(int i=1;i<=n;++i) ++c[read<int>()+1];
tot=0,memset(head,0,sizeof head);
for(int i=1;i<=24;++i){
add(i-1,i,c[i]);
add(i,i-1,0);
}
for(int i=8;i<=24;++i) add(i,i-8,-r[i]);
for(int i=1;i<=7;++i) add(i,i+16,0); // changeable length
add(24,0,0);
for(int i=1;i<=n;++i)
if(spfa(i)) return printf("%d\n",i),void();
puts("No Solution");
}
int main(){
for(int t=read<int>();t--;) Cashier_Employment();
return 0;
}
静渊以有谋,疏通而知事。
浙公网安备 33010602011771号