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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章