POJ 1275(差分约束系统)

POJ 1275

(1)题意:

 超市要招员工,需要保证每个时间段内都有xi个员工,问至少需要多少个员工。

第一行输入T表示测试数据的组数

第二行24个数,R[i]表示第i小时到第i+1小时内,至少需要几个员工;

之后一个n,表示总共招工的人数;

然后n行,每行一个x表示这个人的工作起始时间ti,他从ti开始工作,工作8个小时。

(2)思路:

先找到人数与工作时间的关系,因为每天都是循环的所以只考虑一天的情况即可。

设s[i]数组表示从这一天的0点开始到第i+1个小时期间至少需要多少个人。

统计每个小时的开始工作的人数tim[i],

然后对每一天的每个小时都有0<=s[i]-s[i-1]<=tim[i];------------(1)

然后考虑需求的限制人数:

如果0<=i<7  s[i]-s[i-8]>=R[i];---------------(2)

如果i>=7 (s[23]-s[i+16]) + s[i]>=R[i];-------------(3)

将(3)式改一下,s[i] - s[i+16]>=R[i] - s[23];

可以发现s[23]是一个定值,所以可以确定s[23]的值,然后二分求解。

因为i-8小于0,所以将所有的i改为i+1,初始化s[0] = 0.

(3)代码:

参考文章

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 1024;
const int INF = 1e9+10;
int vis[maxn],dis[maxn],head[maxn],tot,R[50],tim[50];
struct Node{
	int v,nxt,w;
}cur[maxn<<2];
void Init(){
	memset(head,-1,sizeof(head));
	tot = 0;
}
void Add(int x,int y,int z){
	cur[tot] = Node{y,head[x],z};
	head[x] = tot++;
}
bool spfa(int w){
	for(int i=0;i<=24;i++){
		dis[i] = -INF;vis[i] = 0;
	}
	queue <int> q;
	q.push(0);dis[0] = 0;
	while(!q.empty()){
		int x = q.front();q.pop();vis[x] = 0;
		if(x==24&&dis[x]>w) return false; 
		for(int i=head[x];i!=-1;i=cur[i].nxt){
			int y = cur[i].v;
			if(dis[y]<dis[x]+cur[i].w){
				dis[y] = dis[x]+cur[i].w;
				if(vis[y]==0){
					vis[y] = 1;
					q.push(y);
				}
			}
		}
	}
	return dis[24]<=w;
}
int main(void){
	int T;scanf("%d",&T);
	while(T--){
		int n;
		for(int i=0;i<=23;i++) scanf("%d",&R[i]);
		memset(tim,0,sizeof(tim));
		scanf("%d",&n);
		for(int i=0;i<n;i++){
			int x;scanf("%d",&x);tim[x]++;
		}
		int l = 0,r = n+1,ans = n+1;
		while(l<=r){
			int mid = (l+r)>>1;
			Init();
			for(int i=0;i<=23;i++){
				Add(i,i+1,0);
				Add(i+1,i,-tim[i]);
			}
			
			for(int i=7;i<=23;i++){
				Add(i-7,i+1,R[i]);
			}
			Add(0,24,mid);Add(24,0,-mid);
			for(int i=0;i<7;i++){
				Add(i+17,i+1,R[i]-mid);
			}
			
			if(spfa(mid)==true){
				ans = mid;r = mid-1;
			}
			else l = mid+1;
		}
		if(ans>n) printf("No Solution\n");
		else printf("%d\n",ans);
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/91534402