【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; }
≥
| 欢迎来原网站坐坐! >原文链接<