【POJ 1275】 Cashier Employment(差分约束系统的建立和求解)

Cashier Employment
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 7569   Accepted: 2856

Description

A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hired you to help him, solve his problem. The problem is that the supermarket needs different
number of cashiers at different times of each day (for example, a few cashiers after midnight, and many in the afternoon) to provide good service to its customers, and he wants to hire the least number of cashiers for this job.



The manager has provided you with the least number of cashiers needed for every one-hour slot of the day. This data is given as R(0), R(1), ..., R(23): R(0) represents the least number of cashiers needed from midnight to 1:00 A.M., R(1) shows this number for
duration of 1:00 A.M. to 2:00 A.M., and so on. Note that these numbers are the same every day. There are N qualified applicants for this job. Each applicant i works non-stop once each 24 hours in a shift of exactly 8 hours starting from a specified hour, say
ti (0 <= ti <= 23), exactly from the start of the hour mentioned. That is, if the ith applicant is hired, he/she will work starting from ti o'clock sharp for 8 hours. Cashiers do not replace one another and work exactly as scheduled, and there are enough cash
registers and counters for those who are hired.



You are to write a program to read the R(i) 's for i=0..23 and ti 's for i=1..N that are all, non-negative integer numbers and compute the least number of cashiers needed to be employed to meet the mentioned constraints. Note that there can be more cashiers
than the least number needed for a specific slot.

Input

The first line of input is the number of test cases for this problem (at most 20). Each test case starts with 24 integer numbers representing the R(0), R(1), ..., R(23) in one line (R(i) can be at most 1000). Then there is N, number
of applicants in another line (0 <= N <= 1000), after which come N lines each containing one ti (0 <= ti <= 23). There are no blank lines between test cases.

Output

For each test case, the output should be written in one line, which is the least number of cashiers needed.

If there is no solution for the test case, you should write No Solution for that case.

Sample Input

  1. 1
  2. 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
  3. 5
  4. 0
  5. 23
  6. 22
  7. 1
  8. 10

Sample Output

  1. 1

Source

做到如今为止 做的最麻烦的一个差分约束……

麻烦不是麻烦在求解上。而是建图……而且绝大多数差分约束的难点。都是建图。。毕竟求解就是个裸最短路

这题题意是 一个商店要招聘员工 商店有一个客流表 表示0~23点每点须要的最少员工数

之后一个整数n 表示有n个应聘员工

后面n行 每行一个0~23的整数 表示第i个员工工作的起始时间 每一个员工工作8小时

题目分析完成 条件不多 所以这就是这题的难点……要挖掘非常多隐含条件

设t[i]为商店第i小时须要的员工数 r[i]表示第i小时来应聘的员工数 数组S[i]表示0~i小时总共应聘的员工数

第一个条件 0 <= S[i]-S[i-1] <= r[i]

第二个条件 S[i]-S[i-8] >= t[i] (i-1时i-8招聘的员工刚好下班 因此S[i]-S[i-8]即为第i小时招聘的所有员工)

第三个条件 S[24]-S[0] <= sum(因为要找最少的总招聘人数,所以这里出现了一个未知量,而这个问题就转化成了求最小sum)

把三个问题化成同号 再细化一下 就变成了

S[i-1]-S[i] <= 0

S[i]-S[i-1] <= r[i]

S[i-8]-S[i] <= -t[i](0 < i <= 8)

S[i+16]-S[i] <= sum-t[i](8 < i <= 24)

S[24]-S[0] <= sum

找到不等关系就好办一点了 对sum二分 每次更新与sum有关的边权 然后跑最短路 推断一下能不能跑出来(有无负环)

代码例如以下:

  1. #include <iostream>
  2. #include <cmath>
  3. #include <vector>
  4. #include <cstdlib>
  5. #include <cstdio>
  6. #include <cstring>
  7. #include <queue>
  8. #include <list>
  9. #include <algorithm>
  10. #include <map>
  11. #include <set>
  12. #define LL long long
  13. #define Pr pair<int,int>
  14. #define fread() freopen("in.in","r",stdin)
  15. #define fwrite() freopen("out.out","w",stdout)
  16.  
  17. using namespace std;
  18. const int INF = 0x3f3f3f3f;
  19. const int msz = 10000;
  20. const double eps = 1e-8;
  21.  
  22. struct Edge
  23. {
  24. int u,v,w;
  25. };
  26.  
  27. Edge eg[233333];
  28. int w[25],r[25];
  29. int dis[25];
  30. int tp;
  31.  
  32. bool bellman()
  33. {
  34. memset(dis,INF,sizeof(dis));
  35. dis[0] = 0;
  36.  
  37. for(int i = 0; i <= 24; ++i)
  38. for(int j = 0; j < tp; ++j)
  39. if(dis[eg[j].v] > dis[eg[j].u]+eg[j].w)
  40. dis[eg[j].v] = dis[eg[j].u]+eg[j].w;
  41.  
  42. //判负环
  43. for(int j = 0; j < tp; ++j)
  44. if(dis[eg[j].v] > dis[eg[j].u]+eg[j].w)
  45. return false;
  46.  
  47. return true;
  48. }
  49.  
  50. void Add(int u,int v,int w)
  51. {
  52. eg[tp].u = u;
  53. eg[tp].v = v;
  54. eg[tp++].w = w;
  55. }
  56.  
  57. //重建与sum有关的边
  58. void buildgraph(int sum)
  59. {
  60. tp = 64;
  61. for(int i = 1; i < 9; ++i)
  62. Add(i,i+16,sum-w[i]);
  63. Add(24,0,-sum);
  64. }
  65.  
  66. int main()
  67. {
  68. int t,x,n,low,high;
  69.  
  70. scanf("%d",&t);
  71. while(t--)
  72. {
  73. tp = 0;
  74.  
  75. high = 0;
  76. for(int i = 1; i <= 24; ++i)
  77. scanf("%d",&w[i]);
  78.  
  79. memset(r,0,sizeof(r));
  80. scanf("%d",&n);
  81. high = n;
  82.  
  83. while(n--)
  84. {
  85. scanf("%d",&x);
  86. r[x+1]++;
  87. }
  88.  
  89. //边权不变的边(与sum无关的边)
  90. for(int i = 1; i <= 24; ++i)
  91. {
  92. Add(i-1,i,r[i]);
  93. Add(i,i-1,0);
  94. if(i >= 9) Add(i,i-8,-w[i]);
  95. }
  96.  
  97. low = 0;
  98. int ans = INF;
  99. while(low <= high)
  100. {
  101. int mid = (low+high)>>1;
  102.  
  103. buildgraph(mid);
  104. if(bellman())
  105. {
  106. ans = mid;
  107. high = mid-1;
  108. }else low = mid+1;
  109. }
  110.  
  111. if(ans == INF) puts("No Solution");
  112. else printf("%d\n",ans);
  113. }
  114.  
  115. return 0;
  116. }

id=1275">

【POJ 1275】 Cashier Employment(差分约束系统的建立和求解)的更多相关文章

  1. poj 1275 Cashier Employment - 差分约束 - 二分答案

    A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its n ...

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

    [HDU 1529]Cashier Employment(差分约束系统) 题面 有一个超市,在24小时对员工都有一定需求量,表示为\(r_i\),意思为在i这个时间至少要有i个员工,现在有n个员工来应 ...

  3. 图论(差分约束系统):POJ 1275 Cashier Employment

    Cashier Employment Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7651   Accepted: 288 ...

  4. POJ 1275 Cashier Employment 挺难的差分约束题

    http://poj.org/problem?id=1275 题目大意: 一商店二十四小时营业,但每个时间段需求的雇员数不同(已知,设为R[i]),现有n个人申请这份工作,其可以从固定时间t连续工作八 ...

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

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

  6. POJ 1275 Cashier Employment(差分约束)

    http://poj.org/problem?id=1275 题意 : 一家24小时营业的超市,要雇出纳员,需要求出超市每天不同时段需要的出纳员数,午夜只需一小批,下午需要多些,希望雇最少的人,给出每 ...

  7. poj 1275 Cashier Employment

    http://poj.org/problem?id=1275 #include <cstdio> #include <cstring> #include <algorit ...

  8. POJ 1275-Cashier Employment(差分约束系统)

    题目地址:id=1275">POJ 1275 题意: 给出一个超市24小时各须要R[i]个雇员工作,有N个雇员能够雇佣.他们開始工作时间分别为A[i],求须要的最少的雇员人数. 思路: ...

  9. 【POJ1275】Cashier Employment 差分约束

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

随机推荐

  1. Linux安装64位Mysql5.7.22

    以安装在/usr/local目录下为例 1.下载安装包地址:https://dev.mysql.com/downloads/file/?id=476936,安装包保存到/usr/local 2.解压: ...

  2. Kafka生产者----向kafka写入数据

    开发者可以使用kafka内置的客户端API开发kafka应用程序.除了内置的客户端之外,kafka还提供了二进制连接协议,也就是说,我们直接向kafka网络端口发送适当的字节序列,就可以实现从Kafk ...

  3. Visual Studio 2013/2015/2017快捷键(转载)

    本文为转载文章,原文:[心存善念]  [Fonour] 项目相关的快捷键 Ctrl + Shift + B = 生成项目 Ctrl + Alt + L = 显示 Solution Explorer(解 ...

  4. KBE_那些事

    批处理文件不要放在工具栏执行,这里有坑:工具栏运行批处理文件,当前路径(%cd%)不是批处理文件所在路径 日志的输出(DEBUG_MSG 和 INFO_MSG)都被输出在({资产库}/logs/*.l ...

  5. css3新特性学习系列 -- border

    css3新特性 border属性(border-radius.border-image.box-shadow)详解 1.border-radius  圆角 支持:IE9+ 用法: border-rad ...

  6. docker安装配置lnmp

    一.安装配置docker 1.下载docker:yum install -y docker 2.设置docker远程镜像地址为国内路径:curl -sSL https://get.daocloud.i ...

  7. Python:webshell 跳板机审计服务器

    1.修改paramiko源码包实现 https://github.com/paramiko/paramiko/tree/1.10.1 下载源码包 unzip paramiko-1.10.1.zip p ...

  8. 3.2.8 sed 的运作

        sed 的工作方式相当直接.命令行上的每个文件会依次打开与读取.如果没有文件,则使用标准输入,文件名“-”(单个破折号)可用于表示标准输入.       [many@avention Desk ...

  9. em的理解

    em 版本:CSS1 说明: 自己的理解: 注意地方: 浏览器默认大小为16px. 谷歌浏览器最小字体为12px. font-size;有继承性. 判断步骤: []看该元素本身有没有设置字体大小: 有 ...

  10. Python之条件 循环和其他语句 2014-4-6

    #条件 循环和其他语句 23:30pm-1:431.print和import的更多信息 使用逗号将多个表达式输出 >>> print 'age:',42 age: 42 >&g ...