pku 1275 Cashier Employment

【题目大意】: 给出一个超市24小时各需要R[i]个雇员工作,有N个雇员可以雇佣,他们开始工作时间分别为A[i],求需要的最少的雇员人数。

这题目在黑书上有详细的解析,题目的关键是在构图上,把约束条件找出来,再按照条件加边就OK了,不过,我是参考课件里面才过的

【算法分析】: 用差分约束,难点是建立模型。设X[i]0-i小时内工作的人数(X[24]即为所求)R[i]为第(i-1)-i小时时需要在工作的人数,A[i]可以在第i-1小时开始工作。可以建立起以下约束不等式:

0 <= X[i]-X[i-1] <= A[i];  1 <= I <= 24;

X[i] – X[i-8] >= R[i];   8 <= I <= 24;

X[24] – (X[16+i]-X[i]) >= R[i];  1 <= I < 8;

统一化为<=不等式,则可化为求X[0]-X[24] <= --ans; 即求240的最短距离。如果化为>=不等式,则比较直观,X[24]- X[0] >= ans; 024的最长距离。如果有圈出现则无解。二分答案找到最小的ans,使得约束系统有解。特别注意一点,X[24]-X[0] >= ans也是要作为一个约束不等式,添加(0, 24, ans)的边。

#include<iostream>
#include<string>
#define MAXINT 9999999
#define MAXN 30
using namespace std;
int dis[MAXN],num;
int n,m,r[25],t[25];
//r[],(i-1)-i小时内需要工作人数.
//t[],第(i-1)小时可以开始工作的人数.
struct edge
{
	int u,w,v;
}e[MAXN*5];
void add(int u,int v,int w)
{
	e[num].u=u;
	e[num].w=w;
	e[num].v=v;
	 num++;
}
bool bellman_ford()
{
	for(int i=0;i<=24;i++)
		dis[i]=-MAXINT;
	dis[24]=0;
	bool rel=false;
	for(int i=1;i<=24;i++)
	{
		for(int j=0;j<num;j++)
		{
			int x=e[j].v;
			if(dis[x]>dis[e[j].u]+e[j].w)
			{
				dis[x]=dis[e[j].u]+e[j].w;
				rel=true;
			}
		}
		if(!rel) //没有可松弛操作,则一定有解了
			return true;
	}
	for(int j=0;j<num;j++)
	{
		int x=e[j].v;
		if(dis[x]>dis[e[j].u]+e[j].w)
			return false;
	}
	return true;
}
int main()
{
	int n1,cas,a,minn,maxn;
	cin>>cas;
	while(cas--)
	{	
		minn=-1;
		memset(t,0,sizeof(t));
		for(int i=1;i<=24;i++)
		{
			cin>>r[i];
			if(r[i]>minn) minn=r[i];
		}
		cin>>n1;
		maxn=n1;
		//因为最少要有max(r[i])个人,最多有n1个人。
		for(int i=0;i<n1;i++)
		{
			cin>>a;
			t[++a]++;
		}
		num=0;
		for(int i=1;i<=24;i++)
		{
			add(i-1,i,t[i]);
			add(i,i-1,0);
		}
		for(int i=8;i<=24;i++)
			add(i,i-8,-r[i]);
		int edge_num=num;//edge_num保存已经加好的边数
		int res=-1;
		int left=minn,right=maxn,mid;
		while(left<=right)//二分枚举答案
		{
			num=edge_num;
			mid=(right+left)/2;
			for(int i=1;i<8;i++)
				add(i,i+16,-r[i]+mid);
			add(24,0,-mid);
			//这里其实有个隐藏的约束条件X[24]-X[0]>=mid
			//转换为X[0]-X[24] <= -mid;
			if(bellman_ford())//如果有解,那么再找更小的解
			{
				right=mid-1;res=mid;
			}
			else left=mid+1;
		}
		if(res==-1)
			cout<<"No Solution"<<endl;
		else cout<<res<<endl;
	}
	return 0;
}

 

原文地址:https://www.cnblogs.com/nanke/p/2139349.html