zoukankan      html  css  js  c++  java
  • 【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
    ",i);
    			return ;
    		}
    	}
    	printf("No Solution
    ");
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)	work();
    	return 0;
    }

  • 相关阅读:
    堆栈学习
    需要阅读的书籍
    Rust Book Lang Ch.19 Fully Qualified Syntax, Supertraits, Newtype Pattern, type aliases, never type, dynamic sized type
    Rust Lang Book Ch.19 Placeholder type, Default generic type parameter, operator overloading
    Rust Lang Book Ch.19 Unsafe
    Rust Lang Book Ch.18 Patterns and Matching
    Rust Lang Book Ch.17 OOP
    Rust Lang Book Ch.16 Concurrency
    Rust Lang Book Ch.15 Smart Pointers
    HDU3966-Aragorn's Story-树链剖分-点权
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6786239.html
Copyright © 2011-2022 走看看