393. 雇佣收银员

题目链接

393. 雇佣收银员

一家超市要每天 24 小时营业,为了满足营业需求,需要雇佣一大批收银员。

已知不同时间段需要的收银员数量不同,为了能够雇佣尽可能少的人员,从而减少成本,这家超市的经理请你来帮忙出谋划策。

经理为你提供了一个各个时间段收银员最小需求数量的清单 R(0),R(1),R(2),,R(23)

R(0) 表示午夜 00:00 到凌晨 01:00 的最小需求数量,R(1) 表示凌晨 01:00 到凌晨 02:00 的最小需求数量,以此类推。

一共有 N 个合格的申请人申请岗位,第 i 个申请人可以从 ti 时刻开始连续工作 8 小时。

收银员之间不存在替换,一定会完整地工作 8 小时,收银台的数量一定足够。

现在给定你收银员的需求清单,请你计算最少需要雇佣多少名收银员。

输入格式

第一行包含一个不超过 20 的整数,表示测试数据的组数。

对于每组测试数据,第一行包含 24 个整数,分别表示 R(0),R(1),R(2),,R(23)

第二行包含整数 N

接下来 N 行,每行包含一个整数 ti

输出格式

每组数据输出一个结果,每个结果占一行。

如果没有满足需求的安排,输出 No Solution

数据范围

0R(0)1000,
0N1000,
0ti23

输入样例:

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 0 23 22 1 10

输出样例:

1

解题思路

差分约束,二分

a[i] 表示 i 时刻申请的人数,x[i] 表示选择的 i 时刻的人数,则有 0x[i]a[i],且对于限制 r[i],即 x[i]+x[i1]++x[i7]r[i](这里 i7),考虑前缀和,则所有的 i 右移一位,i8 时,有 s[i]s[i8]r[i],而对于 1i7,有 s[i]+s[24]s[16+i]r[i],而这里有 s[i],s[24],s[16+i] 三个变量,不符合差分约束形式,这里由于 s[24] 不变,可以考虑固定 s[24],同时由于人数越多越容易满足要求,即可二分 s[24],求解最小值,据此 spfa 求解最长路即可

  • 时间复杂度:O(24klogn)

代码

// Problem: 雇佣收银员 // Contest: AcWing // URL: https://www.acwing.com/problem/content/395/ // Memory Limit: 10 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=25; int r[N],n,a[N],d[N],cnt[N]; vector<PII> adj[N]; bool v[N]; void build(int c) { for(int i=0;i<N;i++)adj[i].clear(); adj[0].pb({24,c}),adj[24].pb({0,-c}); for(int i=1;i<=7;i++)adj[16+i].pb({i,r[i]-c}); for(int i=8;i<N;i++)adj[i-8].pb({i,r[i]}); for(int i=1;i<N;i++)adj[i-1].pb({i,0}),adj[i].pb({i-1,-a[i]}); } bool spfa(int c) { build(c); memset(d,-0x3f,sizeof d); memset(cnt,0,sizeof cnt); memset(v,0,sizeof v); queue<int> q; q.push(0); v[0]=true; d[0]=0; while(q.size()) { int x=q.front(); q.pop(); v[x]=false; for(auto t:adj[x]) { int y=t.fi,w=t.se; if(d[y]<d[x]+w) { d[y]=d[x]+w; cnt[y]=cnt[x]+1; if(cnt[y]>=N)return false; if(!v[y])v[y]=true,q.push(y); } } } return true; } int main() { int t; for(cin>>t;t;t--) { for(int i=1;i<N;i++)cin>>r[i],a[i]=0; cin>>n; for(int i=1;i<=n;i++) { int t; cin>>t; a[t+1]++; } int l=0,r=n; while(l<r) { int mid=l+r>>1; if(spfa(mid))r=mid; else l=mid+1; } if(spfa(l))cout<<l<<'\n'; else puts("No Solution"); } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16581783.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示