poj1275 「一本通 3.4 例 2」出纳员问题

在这里插入图片描述

analysis

有点麻烦

这道题的题解在

数与图的完美结合
-------浅析差分约束系统
华中师大一附中 冯威

这篇国集论文里面有,这篇论文很不错

还是说一下大概的思路(自己敲了半天也没敲出来思路):

设num[i] 为来应聘的在第i个小时开始工作的人数
r[i] 为第i个小时至少需要的人数
x[i] 为招到的在第i个小时开始工作的人数
根据题意有:
0 <= x[i] <= num[i]
x[i] + x[i-1] + …+ x[i-7] >= r[i] (题目中的连续工作8小时)
再设 s[i] = x[1] + … + x[i]
则有: s[i] – s[i-1] >= 0
s[i-1] – s[i] >= –num[i]
s[i] – s[i-8] >= r[i], 8 <= i <= 24
s[i] – s[i+16] >= r[i] – s[24], 1<= i <= 7
还需要添加一个隐藏不等式: s[24] – s[0] >= ans(枚举的答案)
通过枚举s[24],来检测是否满足条件(题目是求最小值,即求最长路,以0为源点),每次跑完spfa后,就看算出来的s[24]和枚举的是不是一样就行,因为spfa求出来的是当前约束条件下的最小值,于是只要从小到大枚举ans和s[24]相等了就说明当前的最小值是ans

这道题有待消化(总觉得有哪里没弄懂,但又说不出来)

code

#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
template<typename T>void read(T &x){
	char r=getchar();T neg=1;x=0;
	while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
	while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
	x*=neg;
}
int T;
int R[50];
int num[50];
int n;
struct node{
	int e;
	int w;
	int nxt;
}edge[50<<2];
int head[50];
int cnt=0;
inline void addl(int u,int v,int w){
	edge[cnt].e=v;
	edge[cnt].w=w;
	edge[cnt].nxt=head[u];
	head[u]=cnt++;
}
inline void buildgraph(int w){
	clean(head,-1);
	cnt=0;
	addl(0,24,w);
	loop(i,1,24){
		addl(i-1,i,0);
		addl(i,i-1,-num[i]);
		if(i>=9)
			addl(i-8,i,R[i]);
		else if(i<=8)
			addl(i+16,i,R[i]-w);
	}
}
queue<int>q;
int dis[50];
bool insta[50];
int in[50];
bool spfa(int ans){
	loop(i,1,40)
		dis[i]=-0x3f3f3f3f;
	clean(insta,false);
	clean(in,0);
	dis[0]=0;
	++in[0];
	q.push(0);
	while(q.empty()==false){
		int f=q.front();
		q.pop();
		insta[f]=false;
		for(int i=head[f];i!=-1;i=edge[i].nxt){
			int v=edge[i].e;
			if(dis[v]<dis[f]+edge[i].w){
				dis[v]=dis[f]+edge[i].w;
				if(!insta[v]){
					insta[v]=true;
					q.push(v);
					if(++in[v]>24){
						while(q.empty()==false)
							q.pop();
						return false;
					}
				}
			}
		}
	}
	return (dis[24]==ans)?true:false;
}
int main(){
	#ifndef ONLINE_JUDGE
	freopen("datain.txt","r",stdin);
	#endif
	read(T);
	while(T--){
		clean(head,-1);
		cnt=0;
		loop(i,1,24)
			read(R[i]);
		read(n);
		clean(num,0);
		loop(i,1,n){
			int ti;
			read(ti);
			++num[ti+1];
		}
		bool flag=false;
		loop(i,0,n){
			buildgraph(i);
			if(spfa(i)){
				printf("%d\n",i);
				flag=true;
				break;
			}
		}
		if(!flag)
			printf("No Solution\n");
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章