http://poj.org/problem?id=1275

题目大意:

一商店二十四小时营业,但每个时间段需求的雇员数不同(已知,设为R[i]),现有n个人申请这份工作,其可以从固定时间t连续工作八个小时,问在满足需求的情况下最小需要多少个雇员。

思路:

挺难的。。看了别人的思路搞半天。。

设num[ i ]为i时刻能够开始工作的人数,x[ i ]为实际雇佣的人数,那么x[ I ]<=num[ I ]。 设r[ i ]为i时刻至少需要工作的人数,于是有如下关系:

x[ I-7 ]+x[ I-6 ]+…+x[ I ]>=r[ I ] 

  设s[ I ]=x[ 1 ]+x[ 2 ]…+x[ I ],

  得到

s[ I ]-s[ I-1 ]>=0            (0<=I<=23)

s[ I-1 ]-s[ I ]>=-num[ I ]       (0<=I<=23)

s[ I ]-s[ I-8 ]>=r[ I ]         (8<=I<=23)

s[ I ]-s[ I+16 ]>=r[ I ]-s[ 23 ]  (0<=I<= 7)

这里出现了小的困难,我们发现以上式子并不是标准的差分约束系统,因为在最后一个式子中出现了三个未知单位。但是注意到其中跟随 I变化的只有两个,于是s[23]就变得特殊起来,看来是需要我们单独处理,于是我们把 s[ 23 ]当作已知量放在右边。

经过这样的整理,整个图就很容易创建了,将所有形如 A-B>=C 的式子 我们从节点B 引出一条有向边指向 A  边的权值为C  (这里注意由于左右确定,式子又是统一的>=的不等式,所以A和B是相对确定的,边是一定是指向A的) ,图就建成了 。 最后枚举所有s[ 23 ]的可能值,对于每一个s[23],我们都进行一次常规差分约束系统问题的求解,判断这种情况是否可行,如果可行求出需要的最优值,记录到Ans中,最后的Ans的值即为所求。

不过按上面的死活出不来。最后和别人一样下标都+1过了。。。。。不知道嘛状况。

还有要加上0->24的边(看POJ discuss的)

大牛解释如下:

为避免负数,时间计数1~24。令:

R[i] i时间需要的人数 (1<=i<=24)

T[i] i时间应聘的人数 (1<=i<=24)

x[i] i时间录用的人数 (0<=i<=24),其中令x[0]=0

再设s[i]=x[0]+x[1]+……+x[i] (0<=i<=24),

由题意,可得如下方程组:

(1) s[i]-s[i-8]>=R[i]        (8<=i<=24)

(2) s[i]-s[16+i]>=R[i]-s[24] (1<=i<=7)

(3) s[i]-s[i-1]>=0           (1<=i<=24)

(4) s[i-1]-s[i]>=-T[i]       (1<=i<=24)





这个差分约束有个特殊的地方,(2)的右边有未知数s[24]。

这时可以通过枚举s[24]=ans来判断是否有可行解。

即(2)变形为(2') s[i]-s[16+i]>=R[i]-ans (1<=i<=7)

再通过SPFA求解(1)(2')(3)(4)。





不过最后有可能出现这种情况:

(1)(2')(3)(4)虽然有解,但求出的s[24]小于代入(2')里的ans!

这时,显然得到的s[]不满足原来的(2)了(请仔细比较(2)与(2'))。

不过虽然得到的解不满足原方程组,但这并不代表(1)(2)(3)(4)在s[24]=ans时没有可行解!

此外,值得注意的是,当得到的s[24]>ans时,虽然s[24]不一定是最优解,但把ans置成s[24]后,确实是可行解。





所以,简单把(2)置换成(2')是有问题的!

为了等价原命题,必须再加上条件:s[24]>=ans

这就是所谓加出来的那条边(5) s[24]-s[0]>=ans

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=23+10;
const int MAXM=3000;
const int INF=-9999999;
struct edge
{
int to;
int val;
int next;
}e[MAXM];
int head[MAXN],dis[MAXN],len,m;
int num[MAXN],r[MAXN]; void add(int from,int to,int val)
{
e[len].to=to;
e[len].val=val;
e[len].next=head[from];
head[from]=len++;
} bool spfa(int k)
{
int start=0;
for(int i=0;i<=24;i++)
dis[i]=INF; bool vis[MAXN]={0};
int cnt[MAXN]={0};
queue<int> q;
q.push(start);
vis[start]=1;
cnt[start]=1;
dis[start]=0;
while(!q.empty())
{
int cur=q.front();
q.pop();
vis[cur]=false;
for(int i=head[cur];i!=-1;i=e[i].next)
{
int id=e[i].to;
if(dis[id] < dis[cur] + e[i].val)
{
dis[id]=dis[cur] + e[i].val;
if(!vis[id])
{
if(++cnt[id] > 24)
return false;
vis[id]=true;
q.push(id);
}
}
}
}
if(k!= dis[24])
return false;
return true;
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(num,0,sizeof(num)); for(int i=1;i<=24;i++)
scanf("%d",&r[i]); scanf("%d",&m);
for(int i=0;i<m;i++)
{
int t;
scanf("%d",&t);
num[t+1]++;
} bool ok=false;
for(int k=0;k<=m;k++)
{
memset(head,-1,sizeof(head));
len=0;
add(0,24,k);
for(int i=1;i<=24;i++)
{
add(i-1,i,0);
add(i,i-1,-num[i]); if(i>8)
add(i-8,i,r[i]);
else
add(i+16,i,r[i]-k);
}
if(spfa(k) )
{
ok=true;
break;
} }
if(!ok)
puts("No Solution");
else
printf("%d\n",dis[24]); }
return 0;
}

POJ 1275 Cashier Employment 挺难的差分约束题的更多相关文章

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

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

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

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

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

  4. poj 1275 Cashier Employment

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

  5. 【转】最短路&差分约束题集

    转自:http://blog.csdn.net/shahdza/article/details/7779273 最短路 [HDU] 1548 A strange lift基础最短路(或bfs)★254 ...

  6. 转载 - 最短路&差分约束题集

    出处:http://blog.csdn.net/shahdza/article/details/7779273 最短路 [HDU] 1548    A strange lift基础最短路(或bfs)★ ...

  7. POJ - Problem 1275 - Cashier Employment

    · 对于差分约束,题目要求求什么便设什么,令$Sum[i]$表示由$0 ~ i$的雇佣人数. · 要充分利用题目所给条件,令$Have[i]$表示i时刻申报的人数,$Need[i]$表示i时刻需要的人 ...

  8. HDU [1529] || POJ [P1275] Cashier Employment

    经典的差分约束+二分答案. 本题的难点在于如何建图. 设x[i] 表示第i个小时可以开始工作的有多少个人. num[i] 表示第i个小时最少需雇佣多少人. s[i] 表示1...i小时实际开始工作的有 ...

  9. POJ 3159 Candies(SPFA+栈)差分约束

    题目链接:http://poj.org/problem?id=3159 题意:给出m给 x 与y的关系.当中y的糖数不能比x的多c个.即y-x <= c  最后求fly[n]最多能比so[1] ...

随机推荐

  1. Scrum中的产品需求预审

    原文作者:Mike Cohn 为了保持产品待办事项(product backlog)的整洁有序,我们须要召开product backlog refinement会议(有时也叫product backl ...

  2. Python: PS 图像调整--对比度调整

    本文用 Python 实现 PS 里的图像调整–对比度调整.具体的算法原理如下: (1).nRGB = RGB + (RGB - Threshold) * Contrast / 255 公式中,nRG ...

  3. c++值传递,指针传递,引用传递以及指针与引用的区别

    值传递: 形参是实参的拷贝,改变形参的值并不会影响外部实参的值.从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入, 不能传出.当函数内部需要修改参数,并且不希望这个改变影 ...

  4. 如何让hudson的两个job共用一个svn工作目录

    作者:朱金灿 来源:http://blog.csdn.net/clever101 现在我的需求是这样的:一个软件需要编译完全版本和基础版本,完全版本的基础功能较多,基础版本只包含了基础功能.有时只需要 ...

  5. BootStrap_Table 学习

    https://blog.csdn.net/heting90/article/details/52248729 $("#realTime_Table").bootstrapTabl ...

  6. spark ml阅读笔记

    参考文档:http://www.cnblogs.com/huliangwen/p/7491797.html

  7. 32款iOS开发插件和工具介绍[效率]

    插件和工具介绍内容均收集于网络,太多了就不一一注明了,在此谢过!   1.Charles 为了调试与server端的网络通讯协议.经常须要截取网络封包来分析. Charles通过将自己设置成系统的网络 ...

  8. php7 兼容 MySQL 相关函数

    php7 兼容 MySQL 相关函数 PHP7 废除了 ”mysql.dll” ,推荐使用 mysqli 或者 pdo_mysql http://PHP.net/manual/zh/mysqlinfo ...

  9. ubuntu16 升级后找不到 eth0 网卡 的解决方法

    ubuntu16 升级后找不到 eth0 网卡 的解决方法 今天在VPS上一时手痒,执行了升级命令 apt-get update 更新软件包索引,源 apt-get upgrade 更新软件包 apt ...

  10. [NOI.AC#33]bst 线段树

    链接 区间修改,完全二叉树,这引导我们把这棵树看成一棵线段树 .线段树的每一个节点相当于这棵二叉树的节点, 对于区间交换操作,我们对二叉树的每一层从上到下分别考虑,找到L,R在第i层对应的节点修改 这 ...