【POJ1275】Cashier Employment 差分约束

【POJ1275】Cashier Employment

 

题意 超市经历已经提供一天里每一小时需要出纳员的最少数量————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,它们都是非负整数,计算为满足上述限制需要雇佣的最少出纳员数目。

题解:差分约束还是不熟啊

这题的时间是循环的,所以列不等式不是那么容易

设a[i]为每一时刻最少雇佣的收银员数量,b[i]为每一时刻的总申请数,f[i]为0~i时刻实际雇佣的收银员数,根据题目要求并变形,有以下不等式关系: f[i]-f[i-1]0   (1<=i<=24)    ——每一时刻雇佣数量大于等于0
f[i]-f[i-1]b[i]  (1<=i<=24)  ——每一时刻雇佣数量不超过总申请数
f[i]-f[i-8]a[i]  (8<=i<=24)  ——实际雇佣数量满足最小需求

f[i]-f[i+16]≥a[i]-f[24]  (1<=i<=7)    ——实际雇佣数量满足最小需求,注意i可能跨天

但是f[24]也是个变量,所以我们令ans=f[24],然后枚举ans,用SPFA判负环就好了

这样做会不会有什么问题?

问题在于f[i]-f[i+16]≥a[i]-f[24]和f[i]=f[i+16]≥a[i]-ans这两个不等式并不等价,前者对变量f[24]也具有一定限制,而后者将其省略掉了。所以,我们只需要令f[24]=ans,就能将错解排除掉,具体地,f[24]≥ans就可以

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
int n,cnt;
int len[1010],dis[1010],to[1010],next[1010],head[1010],val[1010];
int inq[1010],s[1010],r[1010];
queue<int> q;
void add(int a,int b,int c)
{
	to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
int spfa(int ans)
{
	int u,i;
	for(i=1;i<=7;i++)	val[head[i]]=ans-r[i];
	val[head[24]]=-ans;
	memset(dis,0x3f,sizeof(dis));
	memset(len,0,sizeof(len));
	while(!q.empty())	q.pop();
	for(i=0;i<=24;i++)	q.push(i),dis[i]=len[i]=0,inq[i]=1;
	while(!q.empty())
	{
		u=q.front(),q.pop(),inq[u]=0;
		for(i=head[u];i!=-1;i=next[i])
		{
			if(dis[to[i]]>dis[u]+val[i])
			{
				dis[to[i]]=dis[u]+val[i];
				len[to[i]]=len[u]+1;
				if(len[to[i]]>25)	return 0;
				if(!inq[to[i]])
				{
					inq[to[i]]=1;
					q.push(to[i]);
				}
			}
		}
	}
	return 1;
}
void work()
{
	int i,j,a;
	for(i=1;i<=24;i++)	scanf("%d",&r[i]);
	scanf("%d",&n);
	cnt=0;
	memset(head,-1,sizeof(head));
	for(i=1;i<=n;i++)	scanf("%d",&a),s[a+1]++;
	for(i=1;i<=24;i++)	add(i-1,i,s[i]),add(i,i-1,0);
	for(i=8;i<=24;i++)	add(i,i-8,-r[i]);
	for(i=1;i<=7;i++)	add(i,i+16,0);
	add(24,0,0);
	for(i=1;i<=n;i++)
	{
		if(spfa(i))
		{
			printf("%d\n",i);
			return ;
		}
	}
	printf("No Solution\n");
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)	work();
	return 0;
}

 

posted @ 2017-04-29 20:52  CQzhangyu  阅读(414)  评论(1编辑  收藏  举报