出纳员问题
枚举总人数差分约束判可行性
正文
// 原题:https://oj.yecheng.tv/p/T1510
// 题意:24 小时各时段最少需求 R(i),N 个应聘者各有起始时刻 t(连续工作 8 小时),求最少雇佣人数,无解输出 No Solution。
// 思路:差分约束。设 T(i) 为起始时刻在 [0, i - 1] 的人数前缀和,枚举总人数 ans 后用 SPFA 判最长路是否出现正环(无解)。
// 1. 每小时人数约束:i >= 7 时 T(i + 1) - T(i - 7) >= R(i);i < 7 时跨天,写成 T(i + 1) - T(i + 17) >= R(i) - ans。
// 2. 每个时刻上岗人数不超过该时刻的应聘者数,且 T(24) - T(0) 强制等于 ans。
// 复杂度:O(N * 25 * E) 时间 / O(25) 空间
// 易错点:i < 7 的跨天约束里含总人数 ans,减的是枚举值,漏掉这一项会算出偏小的答案。
// 易错点:ans 要从 0 枚举到 N 取第一个可行值,且 T(24) - T(0) = ans 需要正反两条边来固定。
#include <bits/stdc++.h>
using namespace std;
struct Edge{
int to;
int w;
};
vector<Edge> g[25];
int dis[25];
int cnt[25];
bool inq[25];
int R[24];
int num[24];
bool feasible(int ans){
for(int i = 0; i <= 24; i++){
g[i].clear();
}
Edge e1;
e1.to = 24;
e1.w = ans;
g[0].push_back(e1);
Edge e2;
e2.to = 0;
e2.w = -ans;
g[24].push_back(e2);
for(int i = 0; i < 24; i++){
Edge up;
up.to = i + 1;
up.w = 0;
g[i].push_back(up);
Edge down;
down.to = i;
down.w = -num[i];
g[i + 1].push_back(down);
}
for(int i = 7; i < 24; i++){
Edge e;
e.to = i + 1;
e.w = R[i];
g[i - 7].push_back(e);
}
for(int i = 0; i < 7; i++){
Edge e;
e.to = i + 1;
e.w = R[i] - ans;
g[i + 17].push_back(e);
}
queue<int> q;
for(int i = 0; i <= 24; i++){
dis[i] = 0;
cnt[i] = 0;
inq[i] = true;
q.push(i);
}
while(!q.empty()){
int u = q.front();
q.pop();
inq[u] = false;
for(int i = 0; i < (int)g[u].size(); i++){
int v = g[u][i].to;
int w = g[u][i].w;
if(dis[v] < dis[u] + w){
dis[v] = dis[u] + w;
cnt[v]++;
if(cnt[v] > 25) return false;
if(!inq[v]){
inq[v] = true;
q.push(v);
}
}
}
}
return true;
}
int main(){
int T;
if(!(cin >> T)) return 0;
while(T--){
for(int i = 0; i < 24; i++){
cin >> R[i];
}
int N;
cin >> N;
for(int i = 0; i < 24; i++){
num[i] = 0;
}
for(int i = 0; i < N; i++){
int t;
cin >> t;
num[t]++;
}
int ans = -1;
for(int i = 0; i <= N; i++){
if(feasible(i)){
ans = i;
break;
}
}
if(ans < 0) cout << "No Solution" << "\n";
else cout << ans << "\n";
}
return 0;
}
一本通·提高篇的其它内容
- 活动安排
- 种树
- 喷水装置
- 加工生产调度
- 智力大冲浪
- 数列极差
- 数列分段
- 线段
- 家庭作业
- 钓鱼
- 糖果传递
- 愤怒的牛
- Best Cow Fences
- 曲线
- 数列分段 II
- 扩散
- 灯泡
- 传送带
- 数的划分
- 生日蛋糕
- 小木棍
- Addition Chains
- 埃及分数
- 平板涂色
- 质数方阵
- 靶形数独
- 电路维修
- 魔板
- Knight Moves
- 棋盘游戏
- Keyboarding
- 移动玩具
- 山峰和山谷
- Oulipo
- 图书管理
- Power Strings
- Seekthe Name, Seek the Fame
- Friends
- A Horrible Poem
- Beads
- Antisymmetry
- 门票
- 收集雪花
- 剪花布条
- Power Strings
- Radio Transmission
- OKR-Periods of Words
- 似乎在梦中见过的样子
- Censoring
- Phone List
- The XOR Largest Pair
- Nikitosh 和异或
- Immediate Decodability
- L 语言
- Secret Message 秘密信息
- 背单词
- The Xor-longest Path
- Keywords Search
- 玄武密码
- Censoring