题意:
有一个商店,给出了这个商店一天中每个小时所需要的最少收银员数量
R
[
i
]
R[i]
R[i]。
有
n
n
n个求职者,每个求职者有一个开始工作时刻
t
[
i
]
t[i]
t[i],在
t
[
i
]
t[i]
t[i]时刻后的八小时,这个求职者都在工作。
问老板最少需要雇佣多少个员工,满足商店营业的条件。
思路
构造差分约束系统。(以下下标均从1开始)
令
S
[
i
]
S[i]
S[i]表示前
i
i
i 个小时在工作的员工数量
s
u
m
[
i
]
sum[i]
sum[i]表示时刻
i
i
i 开始工作的员工数量。
那么:
①
S
S
Si
−
-
−
S
S
Si-1
>
=
>=
>=
0
0
0
(
1
<
=
i
<
=
24
)
(1<=i<=24)
(1<=i<=24)
②
S
S
Si-1
−
-
−
S
S
Si
>
=
>=
>=
−
s
u
m
[
i
]
-sum[i]
−sum[i]
(
1
<
=
i
<
=
24
)
(1<=i<=24)
(1<=i<=24)
③
S
S
Si
−
-
−
S
S
Si-8
>
=
>=
>=
R
[
i
]
R[i]
R[i]
(
8
<
=
i
<
=
24
)
(8<=i<=24)
(8<=i<=24)
④
S
S
Si
−
-
−
S
S
Si+16
>
=
>=
>=
R
[
i
]
R[i]
R[i]
+
+
+
S
S
S 24
(
1
<
=
i
<
=
7
)
(1<=i<=7)
(1<=i<=7)
①:第
i
i
i个小时工作的员工数量肯定大于等于0
②:原式是
S
i
−
S
i
−
1
<
=
s
u
m
[
i
]
S_{i} -S_{i-1} <=sum[i]
Si−Si−1<=sum[i],表示第
i
i
i个小时工作的员工数量小于等于此时开始工作的员工数量
③:第
i
i
i时刻正在工作的员工数量,一定是从
i
i
i~
i
−
8
i-8
i−8这段时间开始工作的员工数量之和,所以最坏情况这段和必须大于
R
[
i
]
R[i]
R[i]
④:和③差不多意思
建边后二分 S 24 S_{24} S24的值, s p f a spfa spfa跑最长路即可.
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a));
#define lowbit(x) x&-x;
#define debugint(name,x) printf("%s: %d\n",name,x);
#define debugstring(name,x) printf("%s: %s\n",name,x);
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 105;
const int mod = 1e9+7;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int head[maxn],vis[maxn],cnt[maxn],dis[maxn],tol;
struct node{
int u,v,w,nxt;
}E[maxn<<1];
void init(){
mem(vis,0);
mem(cnt,0);
mem(head,-1);
mem(dis,-inf);
tol = 0;
}
void addedge(int u,int v,int w){
E[tol].u = u;
E[tol].v = v;
E[tol].w = w;
E[tol].nxt = head[u];
head[u] = tol++;
}
int spfa(int st,int ed,int mid){
int all = ed;
queue<int>q;
while(!q.empty()) q.pop();
vis[st] = true;
dis[st] = 0;
q.push(st);
while(!q.empty()){
int u = q.front();
q.pop();
vis[u] = false;
//if(u == ed) continue;
for(int i = head[u]; ~i; i = E[i].nxt){
int v = E[i].v;
int w = E[i].w;
if(dis[v] < dis[u]+w){
dis[v] = dis[u]+w;
if(!vis[v]){
vis[v] = true;
cnt[v]++;
if(cnt[v] > all) return 0;
q.push(v);
}
}
}
}
return 1;
}
int sum[55], R[55], t[1005];
int n;
int main(){
//freopen("in.txt","r",stdin);
int _;
for(scanf("%d",&_);_;_--){
mem(sum,0);
for(int i = 1; i <= 24; i++){
scanf("%d", &R[i]);
}
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d",&t[i]);
sum[t[i]+1]++;
}
int l = 0, r = n,ans = -1;
while(l <= r){
int s24 = (l+r)>>1;
init();
addedge(0,24,s24);
for(int i = 1; i <= 24; i++)
addedge(i-1,i,0),addedge(i,i-1,-sum[i]);
for(int i = 8; i <= 24; i++)
addedge(i-8,i,R[i]);
for(int i = 1; i <= 7; i++)
addedge(i+16,i,R[i]-s24);
if(spfa(0,24,s24)){
ans = s24;
r = s24-1;
}else
l = s24+1;
}
if(ans == -1) puts("No Solution");
else printf("%d\n",ans);
}
}