题目:

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 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

Sample Output

1

题意:

  德黑兰的一家每天24小时营业的超市,需要一批出纳员来满足它的需求。超市经理雇佣你来帮他解决一个问题————超市在每天的不同时段需要不同数目的出纳员(例如,午夜只需一小批,而下午则需要很多)来为顾客提供优质服务,他希望雇佣最少数目的纳员。
     超市经历已经提供一天里每一小时需要出纳员的最少数量————R(0),R(1),...,R(23)。R(0)表示从午夜到凌晨1:00所需要出纳员的最少数目;R(1)表示凌晨1:00到2:00之间需要的;等等。每一天,这些数据都是相同的。有N人申请这项工作,每个申请者i在每天24小时当中,从一个特定的时刻开始连续工作恰好8小时。定义ti(0<=ti<=23)为上面提到的开始时刻,也就是说,如果第i个申请者被录用,他(或她)将从ti时刻开始连续工作8小时。
    试着编写一个程序,输入R(i),i=0,...,23,以及ti,i=1,...,N,它们都是非负整数,计算为满足上述限制需要雇佣的最少出纳员数目、在每一时刻可以有比对应R(i)更多的出纳员在工作。

分析:

  因为一开始就知道这是一道差分约束题,于是就往这方面想了。然而可爱的是,还是没有想出来。TAT~

  其实就是不会搞循环的情况,感觉我的不等式这样子就有三个元了TAT。我们设xi为我们选择了xi个在i时间开始工作的员工,先不考虑循环的情况,那么对于时间点i,那么在时间点i这个时刻正在工作的人数为x[i-7]+x[i-6]+...x[i],用sum数组维护x,即为sum[i]-sum[i-8]。于是我们得到不等式sum[i]-sum[i-8]>=need[i]。(need[i]为题目输入的时间点i需要的员工数)

  循环的情况怎么搞呢?对于i(i<=7),那么后面某一段时间开始工作的员工也会影响答案,那么我们得到的不等式就是sum[24]-sum[i+16]+sum[i]>=need[i](这里的时间点我从1~24考虑)。这里有三个未知数啊,怎么办呢,于是我想了很久没有想出来。

  竟然是!!二分枚举一下sum[24]就好了,那么就把sum[24]看成常数把!!看到这里,我哭了,世界上竟有如此低智商的我!!

  好吧...因为如果我们雇x个人可以搞定全部,那么雇多一点人也可以的嘛,这就是某种单调性,于是我们可以二分。最后再连一条24->0的边权为-sum[24]就可以了。

  差分约束...

  对了,还有一些隐性条件,千万不要漏,上一题中已经说过了。

  eg. x[i]-x[i-1]>=0

代码如下:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#include<queue>
#define Maxn 30 int a[Maxn],sum[Maxn];
int first[Maxn],dis[Maxn],cnt[Maxn];
bool inq[Maxn]; struct node
{
int x,y,c,next;
}t[Maxn*];int len; void ins(int x,int y,int c)
{
t[++len].x=x;t[len].y=y;t[len].c=c;
t[len].next=first[x];first[x]=len;
} queue<int > q;
bool spfa(int s)
{
while(!q.empty()) q.pop();
memset(dis,,sizeof(dis));
memset(inq,,sizeof(inq));
memset(cnt,,sizeof(cnt));
dis[s]=;inq[s]=;q.push(s);
while(!q.empty())
{
int x=q.front();q.pop();inq[x]=;
for(int i=first[x];i;i=t[i].next)
{
int y=t[i].y;
if(dis[y]>dis[x]+t[i].c)
{
dis[y]=dis[x]+t[i].c;
if(!inq[y])
{
q.push(y);
inq[y]=;
if(++cnt[y]>) return ;
}
}
}
}
return ;
} bool check(int x)
{
for(int i=;i<=;i++) t[len-+i].c=x-a[i];
t[len].c=-x;
return spfa();
} void ffind(int l,int r)
{
//check(1);
while(l<r)
{
int mid=(l+r)>>;
if(check(mid)) r=mid;
else l=mid+;
}
printf("%d\n",l);
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int x,n;
memset(sum,,sizeof(sum));
for(int i=;i<=;i++) scanf("%d",&a[i]);
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int x;
scanf("%d",&x);
sum[x+]++;
}
len=;
memset(first,,sizeof(first));
for(int i=;i<=;i++) ins(i-,i,sum[i]);
for(int i=;i<=;i++) ins(i,i-,);
for(int i=;i<=;i++) ins(i,i-,-a[i]);
for(int i=;i<=;i++) ins(i,+i,);
ins(,,);
if(!check(n)) {printf("No Solution\n");continue;}
ffind(,n);
}
return ;
}

[poj1275]

2016-04-12 13:51:47

最新文章

  1. 使用markdown编辑evernote(印象笔记)的常用方法汇总
  2. js基础的知识整理
  3. Redis客户端之Spring整合Jedis,ShardedJedisPool集群配置
  4. parent,parents和closest
  5. PHP 时间函数 date 参数详解
  6. IOS开发--C语言入门--如何结合Terminal和Vim开发C语言程序
  7. zoj 2587 Unique Attack 最小割判定
  8. linux系统光盘开机自动挂载-配置本地yum源
  9. (二叉树 递归) leetcode 145. Binary Tree Postorder Traversal
  10. Django 事务操作
  11. 数据库之mysql篇(6)—— mysql常用函数函数/自定义函数
  12. (五)JavaScript 变量
  13. eclipse编译hbase 1.3.1(转)
  14. List自定义排序(可多条件)
  15. React项目中使用HighCharts
  16. Nginx缓存配置之手动清除缓存
  17. sqljdbc.jar 和 sqljdbc4.jar
  18. c++多继承浅析
  19. 【WPF】MVVM动态修改Bingding的另一种思路——用Style样式
  20. TestNG入门--安装和基本介绍

热门文章

  1. Apache Kafka: Next Generation Distributed Messaging System---reference
  2. linux shell less 命令---转
  3. Ⅶ.AngularJS的点点滴滴-- 事件
  4. Android ListView实现仿iPhone实现左滑删除按钮
  5. Spring Mvc和Mybatis的多数据库访问配置过程
  6. 9张思维导图学习Javascript(转)
  7. DedeCMS文章标题前增加所属栏目名称链接
  8. AngularJS Filter用法详解【转+实际测试】 格式化货币
  9. Shell: how to list all db links in oracle DB to generate a flat file (生成dblink列表文件)
  10. PHP 编译问题PEAR package PHP_Archive not installed的解决