poj1275

Cashier Employment

 POJ - 1275 

A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hired you to help him, solve his problem. The problem is that the supermarket needs different number of cashiers at different times of each day (for example, a few cashiers after midnight, and many in the afternoon) to provide good service to its customers, and he wants to hire the least number of cashiers for this job. 

The manager has provided you with the least number of cashiers needed for every one-hour slot of the day. This data is given as R(0), R(1), ..., R(23): R(0) represents the least number of cashiers needed from midnight to 1:00 A.M., R(1) shows this number for duration of 1:00 A.M. to 2:00 A.M., and so on. Note that these numbers are the same every day. There are N qualified applicants for this job. Each applicant i works non-stop once each 24 hours in a shift of exactly 8 hours starting from a specified hour, say ti (0 <= ti <= 23), exactly from the start of the hour mentioned. That is, if the ith applicant is hired, he/she will work starting from ti o'clock sharp for 8 hours. Cashiers do not replace one another and work exactly as scheduled, and there are enough cash registers and counters for those who are hired.

You are to write a program to read the R(i) 's for i=0..23 and ti 's for i=1..N that are all, non-negative integer numbers and compute the least number of cashiers needed to be employed to meet the mentioned constraints. Note that there can be more cashiers than the least number needed for a specific slot. 

Input

The first line of input is the number of test cases for this problem (at most 20). Each test case starts with 24 integer numbers representing the R(0), R(1), ..., R(23) in one line (R(i) can be at most 1000). Then there is N, number of applicants in another line (0 <= N <= 1000), after which come N lines each containing one ti (0 <= ti <= 23). There are no blank lines between test cases.

Output

For each test case, the output should be written in one line, which is the least number of cashiers needed. 
If there is no solution for the test case, you should write No Solution for that case. 

Sample Input

1
1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
5
0
23
22
1
10

Sample Output

1

题意 在一家超市里,每个时刻都需要有营业员看管,
R(i) (0 <= i < 24)表示从i时刻开始到i+1时刻需要的营业员的数目,
现在有N(N <= 1000)个申请人申请这项工作,并且每个申请者都有一个起始工作时间 ti,
如果第i个申请者被录用,那么他会从ti时刻开始连续工作8小时。现在要求选择一些申请者进行录用,
使得任何一个时刻i,营业员数目都能大于等于R(i)。求出至少需要录用多少营业员。

sol:超有趣的差分约束好题,令f[i]表示前i小时的人数总和,pp[i]表示那个小时的申请人数
则有一下约束
0<=f[i]-f[i-1]<=pp[i]
f[i]-f[i-8]>=r[i] 9<=i<=24
f[i]-f[16+i]+f[24]>=r[i] 1<=i<=8
然后因为有三个所以二分f[24]即答案
因为是最小值所以跑最长路
/*
题意 在一家超市里,每个时刻都需要有营业员看管,
R(i) (0 <= i < 24)表示从i时刻开始到i+1时刻需要的营业员的数目,
现在有N(N <= 1000)个申请人申请这项工作,并且每个申请者都有一个起始工作时间 ti,
如果第i个申请者被录用,那么他会从ti时刻开始连续工作8小时。现在要求选择一些申请者进行录用,
使得任何一个时刻i,营业员数目都能大于等于R(i)。求出至少需要录用多少营业员。
*/
#include <queue>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef int ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-'); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-'); x=-x;
    }
    if(x<10)
    {
        putchar(x+'0'); return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('
')
//最小值最长路,最大值最短路 
const int N=30,M=40005,inf=0x3f3f3f3f;
int T,n,r[N],pp[N];
int tot=0,Next[M],to[M],head[N],val[M];
bool Inq[N];
inline void init()
{
    tot=0; memset(head,0,sizeof head);
}
inline void Link(int x,int y,int z)
{
    Next[++tot]=head[x]; to[tot]=y; val[tot]=z; head[x]=tot;
}
int Dis[N],cnt[N];
inline bool spfa(int ans)
{
    int i;
    for(i=0;i<=24;i++) Dis[i]=-inf,cnt[i]=Inq[i]=0;
    queue<int>Que; while(!Que.empty()) Que.pop(); Que.push(0); Dis[0]=0;
    while(!Que.empty())
    {
        int x=Que.front(); Que.pop(); Inq[x]=0;
//        cout<<"x="<<x<<endl;
//        system("pause");
        for(i=head[x];i;i=Next[i])
        {
            if(Dis[to[i]]<Dis[x]+val[i])
            {
                Dis[to[i]]=Dis[x]+val[i];
                if(!Inq[to[i]]) {Que.push(to[i]); Inq[to[i]]=1;}
                if((++cnt[to[i]])>24) return false;
            }
        }
    }
    return (Dis[24]==ans)?true:false;
}
int main()
{
    freopen("poj1275.in","r",stdin);
    int i;
    R(T);
    while(T--)
    {
        for(i=1;i<=24;i++) {pp[i]=0; R(r[i]);}
        R(n); for(i=1;i<=n;i++) pp[read()+1]++;
        int ll=0,rr=n+1,ans=inf;
        while(ll<=rr)
        {
            init();
            int mid=(ll+rr)>>1;
            for(i=1;i<=24;i++) {Link(i-1,i,0); Link(i,i-1,-pp[i]);}
            for(i=9;i<=24;i++) Link(i-8,i,r[i]);
            for(i=1;i<=8;i++) Link(i+16,i,r[i]-mid);
            Link(0,24,mid);
            if(spfa(mid)) ans=mid,rr=mid-1;else ll=mid+1;
//            cout<<ll<<' '<<mid<<' '<<rr<<endl;
        }
        if(ans<=n) Wl(ans); else puts("No Solution");
    }
    return 0;
}
/*
Sample Input
1
1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
5
0
23
22
1
10
Sample Output
1
*/
View Code
 
原文地址:https://www.cnblogs.com/gaojunonly1/p/11194136.html