【题目链接】
【算法】
设Ti为第i小时有多少个出纳员开始工作,Vi表示第i小时有多少个来应聘的出纳员
那么,有 :
1. 0 <= Ti <= Vi
2. Ti + Ti-1 + Ti-2 + Ti-3 + Ti-4 + Ti-5 + Ti-6 + Ti-7 >= Ri
令Si = T1 + T2 + T3 + ... Ti
则 :
1. Si >= Si-1
2. Si - Si-1 <= Vi
3. Si >= Si-8 + Ri( 8 <= i <= 24)
4. Si>= Si+16 - S24 +Ri (1 <= i <= 7)
所以,我们可以枚举S24,用差分约束系统判断是否可行,枚举可以二分
【代码】
#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
#include <stack>
#include <limits.h>
using namespace std;
struct Edge
{
int to,w,nxt;
} e[1010];
int i,n,k,t,l,r,mid,ans,tot,T;
int v[30],R[30],dis[30],head[30];
inline void add(int u,int v,int w)
{
tot++;
e[tot] = (Edge){v,w,head[u]};
head[u] = tot;
}
inline bool spfa(int x)
{
int i,cur,to,w;
queue<int> q;
static bool inq[30];
static int cnt[30];
tot = 0;
memset(head,0,sizeof(head));
memset(inq,false,sizeof(inq));
memset(cnt,0,sizeof(cnt));
memset(dis,255,sizeof(dis));
add(0,24,x);
for (i = 1; i <= 24; i++) add(i,i-1,-v[i]);
for (i = 1; i <= 24; i++) add(i-1,i,0);
for (i = 8; i <= 24; i++) add(i-8,i,R[i]);
for (i = 1; i <= 7; i++) add(i+16,i,R[i]-x);
while (!q.empty()) q.pop();
q.push(0);
dis[0] = 0;
inq[0] = true;
cnt[0] = 1;
while (!q.empty())
{
cur = q.front();
q.pop();
inq[cur] = false;
for (i = head[cur]; i; i = e[i].nxt)
{
to = e[i].to;
w = e[i].w;
if (dis[cur] + w > dis[to])
{
dis[to] = dis[cur] + w;
if (!inq[to])
{
inq[to] = true;
q.push(to);
cnt[to]++;
if (cnt[to] > 24) return false;
}
}
}
}
return dis[24] == x;
}
int main()
{
scanf("%d",&T);
while (T--)
{
memset(v,0,sizeof(v));
for (i = 1; i <= 24; i++) scanf("%d",&R[i]);
scanf("%d",&k);
for (i = 1; i <= k; i++)
{
scanf("%d",&t);
v[t+1]++;
}
l = 1; r = k;
ans = -1;
while (l <= r)
{
mid = (l + r) >> 1;
if (spfa(mid))
{
r = mid - 1;
ans = mid;
} else
l = mid + 1;
}
if (ans == -1) printf("No Solution\n");
else printf("%d\n",ans);
}
return 0;
}