[HDU 1529]Cashier Employment(差分约束系统)

题面

有一个超市,在24小时对员工都有一定需求量,表示为\(r_i\),意思为在i这个时间至少要有i个员工,现在有n个员工来应聘,每一个员工开始工作的时间为\(t_i(i \in [0,23])\),并持续8小时,问最少需要多少员工才能达到每一个时刻的需求。前一天16点后的人统计入下一天

分析

预备知识:(如果你了解过差分约束,可以直接跳过)

首先讲一下差分约束系统的基本定义:如果一个系统由n个变量和m个约束条件组成,形成m个形如\(x_i-x_j≤k\)的不等式(\(i,j∈[1,n],k\)为常数),则称其为差分约束系统(system of difference constraints)。求解差分约束系统,就是找出一组变量x,使得它满足m个约束条件

观察不等式,我们发现它类似于最短路中的不等式\(dist_y \leq dist_x +w(x,y)\)。所以我们可以建图求解这个问题。

首先我们建立一个虚拟源点s,从s向i连边权为0的边,然后对于不等式\(x_i-x_j≤k\),我们连一条j到i的有向边,边权为k.接着跑Bellman-ford或者SPFA求最短路,如果有负环,则无解。否则\(dist_i\)就是一组可行解。如果\(x_i-x_j \geq k\),那么我们只要改跑最长路就可以了,如果有正环,那么就无解。

本题相关

我们要想办法找出这题的约束条件,然后建图求解。

答案显然有单调性,可以考虑二分答案mid。对于日夜24小时循环的问题,可以采取把环复制一遍,形成长度为48的链求解。

设\(d_i\)表示前i小时有多少员工开始工作,\(p_i\)表示第i个小时最多可以请来多少员工开始工作,\(r_i\)表示第i个小时需要员工的个数。

限制1:\(d_i -d_{i-8} \geq r_i (i \geq 8)\) 保证第i小时在工作的员工够用

限制2:\(d_i-d_{i-24} =mid\),即24小时中工作的员工恰好等于答案,可以拆成\(d_i-d_{i-24} \geq mid,d_{i-24}-d_i \geq -mid\)

限制3:\(d_i - d_{i-1} \geq 0\),前缀和显然不会下降

限制4:\(d_i - d_{i-1} \leq p_i\),第i个小时在工作的员工不会超过能来的员工数

然后跑差分约束系统,如果无解就增加mid,否则减少mid

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 1000
#define maxm 10000
#define INF 0x3f3f3f3f
using namespace std;
int n,t;
const int tim=24;
int r[maxn+5],peo[maxn+5];
struct edge {
int from;
int to;
int next;
int len;
} E[maxm*2+5];
int head[maxn+5];
int sz;
void add_edge(int u,int v,int w) {
// printf("%d->%d len=%d\n",u,v,w);
sz++;
E[sz].from=u;
E[sz].to=v;
E[sz].next=head[u];
E[sz].len=w;
head[u]=sz;
} queue<int>q;
int cnt[maxn+5],dist[maxn+5];
bool inq[maxn+5];
bool spfa(int s) {
while(!q.empty()) q.pop();
for(int i=0; i<=tim*2; i++) {
dist[i]=-INF;
cnt[i]=0;
inq[i]=0;
}
q.push(s);
dist[s]=0;
inq[s]=1;
while(!q.empty()) {
int x=q.front();
q.pop();
inq[x]=0;
for(int i=head[x]; i; i=E[i].next) {
int y=E[i].to;
if(dist[y]<dist[x]+E[i].len) {//spfa求最长路
dist[y]=dist[x]+E[i].len;
if(!inq[y]) {
cnt[y]++;
if(cnt[y]>tim*2) return 0;
q.push(y);
inq[y]=1;
}
} }
}
return 1;
} bool check(int mid) {
sz=1;
for(int i=0; i<=tim*2; i++) head[i]=0;
for(int i=1; i<=tim*2; i++) {
if(i>=8) {
//d[i]-d[i-8]>=r[i]
add_edge(i-8,i,r[i]);
}
if(i>=24) {
//实际上是d[i]-d[i-24]=mid,拆成不等式的形式
//d[i]-d[i-24]>=mid
add_edge(i-24,i,mid);
//d[i]-d[i-24]<=mid
add_edge(i,i-24,-mid);
}
//d[i]-d[i-1]>=0
add_edge(i-1,i,0);
//d[i]-d[i-1]<=peo[i]
add_edge(i,i-1,-peo[i]);
}
return spfa(0);
} void ini() {
sz=1;
for(int i=1; i<=tim*2; i++) head[i]=0;
for(int i=1; i<=tim*2; i++) peo[i]=0;
}
int main() {
int x;
scanf("%d",&t);
while(t--) {
for(int i=1; i<=tim; i++) {
scanf("%d",&r[i]);
}
scanf("%d",&n);
ini();
for(int i=1; i<=n; i++) {
scanf("%d",&x);
peo[x+1]++;//默认时间从1开始
}
for(int i=1;i<=tim;i++){//断环为链
r[i+tim]=r[i];
peo[i+tim]=peo[i];
}
int l=0,r=n,mid,ans=n+1;
while(l<=r) {
mid=(l+r)>>1;
if(check(mid)) {
ans=mid;
r=mid-1;
} else l=mid+1;
}
if(ans==n+1) printf("No Solution\n");
else printf("%d\n",ans);
}
}

[HDU 1529]Cashier Employment(差分约束系统)的更多相关文章

  1. HDU.1529.Cashier Employment(差分约束 最长路SPFA)

    题目链接 \(Description\) 给定一天24h 每小时需要的员工数量Ri,有n个员工,已知每个员工开始工作的时间ti(ti∈[0,23]),每个员工会连续工作8h. 问能否满足一天的需求.若 ...

  2. hdu 1529 Cashier Employment(差分约束)

    Cashier Employment Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  3. POJ1275 Cashier Employment[差分约束系统 || 单纯形法]

    Cashier Employment Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7997   Accepted: 305 ...

  4. 【POJ1275】Cashier Employment 差分约束

    [POJ1275]Cashier Employment 题意: 超市经历已经提供一天里每一小时需要出纳员的最少数量————R(0),R(1),...,R(23).R(0)表示从午夜到凌晨1:00所需要 ...

  5. spfa+差分约束系统(C - House Man HDU - 3440 )+对差分约束系统的初步理解

    题目链接:https://cn.vjudge.net/contest/276233#problem/C 题目大意:有n层楼,给你每个楼的高度,和这个人单次的最大跳跃距离m,两个楼之间的距离最小是1,但 ...

  6. POJ1275/ZOJ1420/HDU1529 Cashier Employment (差分约束)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 题意:一商店二十四小时营业,但每个时间段需求的出纳员不同,现有n个人申请这份工作, ...

  7. hdu1529 Cashier Employment[差分约束+二分答案]

    这题是一个类似于区间选点,但是有一些不等式有三个未知量参与的情况. 依题意,套路性的,将小时数向右平移1个单位后,设$f_i$为前$i$小时工作的人数最少是多少,$f_{24}$即为所求.设$c_i$ ...

  8. Cashier Employment 差分约束

    题意:有一个超市需要一些出纳员,已给出这个超市在各个时间段(0-1,1-2,2-3...共24个时间段)至少需要的出纳员数目,现在前来应聘有n个人,每个人都有一个固定的开始工作的时间,这也意味着从这个 ...

  9. POJ1275 Cashier Employment(差分约束)

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9078   Accepted: 3515 Description A sup ...

随机推荐

  1. ant-design如果按需加载组件

    Ant Design React按需加载 Ant Design是阿里巴巴为React做出的组件库,有统一的样式及一致的用户体验 官网地址:https://ant.design 1.安装: npm in ...

  2. Centos安装ifstat统计网络流量

    原文地址: http://www.winvps.org/post/504.html 下载 ifstat ,  http://gael.roualland.free.fr/ifstat/ifstat-1 ...

  3. .net Console.ReadLine无效

    代码中出现了 Console.ReadLine无效解决办法:把应用程序的输出类型改为 控制台应用程序

  4. 阿里P8技术栈

  5. FMC141-4路 250Msps/16bits ADC, FMC板卡

    FMC141-4路 250Msps/16bits ADC, FMC板卡 一.产品概述: 本板卡基于 FMC 标准板卡,实现 4 路 16-bit/250Msps ADC 功能.遵循 VITA 57 标 ...

  6. 【学习】005 线程池原理分析&锁的深度化

    线程池 什么是线程池 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序 都可以使用线程池.在开发过程中,合理地使用线程池能够带来3个好处. 第一:降低资源消耗.通过重复 ...

  7. 2018-11-01-weekly

    Algorithm 107. 二叉树的层次遍历 II What 给定一个二叉树,返回其节点值自底向上的层次遍历. (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历).例如:给定二叉树 [3,9 ...

  8. 前端每日实战:30# 视频演示如何用纯 CSS 创作一个晃动的公告板

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/wjZoGV 可交互视频教程 此视频 ...

  9. hdu 5212 : Code【莫比乌斯】

    题目链接 题给代码可以转化为下面的公式 然后用F[n]记录公约数为n的(a[i],a[j])对数,用f[n]记录最大公约数为n的(a[i],a[j])对数 之后枚举最大公约数d 至于求F[n],可以先 ...

  10. 在vue项目中,解决如何在element表格中循环出图片列!

    效果图: 1,vue项目环境 2,引入element-ui组件 3,制作表格 此处省去制作循环表格数据那步,想看的可以找回我的博客:element中的表格处理:循环出表格数据 今天想在表格出循环出一列 ...