【题目链接】
【算法】
设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 "); else printf("%d ",ans); } return 0; }