poj1275

题意:给出一个超市一天24小时每个小时需要的人手,再给出n个应聘者的上班时间,每个人每次上班连续8个小时,问最少要聘请多少人。

分析:c[i]表示第i小时需要的人手,t[i]表示第i小时开工的人数,s[i]表示最终聘请的人里面在[0,i]之间开始工作的人的总数。转化为不等式组:s[i+1]-s[i]>=0(i+1小时开始上班的人数最少是0),s[i+1]-s[i]<=t[i+1](i+1小时开始上班的人数最多为t[i+1]),j+8=i && s[i]-s[j]>=c[i],i=(j+8)%24 && s[i]-s[j]>=c[i]-mid(满足i小时的人手需求,mid是最终聘请人数可能的范围[left,right]的中值,要用二分法查找满足条件的最小答案),s[24]-s[0]>=mid(其实是等于)。

#include<cstdio>
#include<queue>
using namespace std;
struct weighed_arc
{
    int v,weight,next;
};
weighed_arc arc[100000];
queue<int> que;
int t[25],c[25],caseNum,n,m,sum,first[25],visited[25];
bool inque[25];
bool spfa(int s)
{
    int dis[25];
    dis[0]=0;
    for(int i=0;i<25;i++)
    {
        visited[i]=0;
        dis[i]=-0xfffff;
        inque[i]=false;
    }
    dis[0]=0;
    visited[0]=1;
    que.push(0);
    inque[0]=true;
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        inque[u]=false;
        for(int i=first[u];i!=-1;i=arc[i].next)
        {
            int v=arc[i].v;
            if(dis[v]<dis[u]+arc[i].weight)
            {
                dis[v]=dis[u]+arc[i].weight;
                if(!inque[v])
                {
                    que.push(v);
                    inque[v]=true;
                    visited[v]++;
                    if(visited[v]>=25)
                        return false;
                }
            }
        }
    }
    return true;
}
int main()
{
    scanf("%d",&caseNum);
    while(caseNum--)
    {
        for(int i=1;i<=24;i++)
            scanf("%d",&c[i]);
        scanf("%d",&n);
        for(int i=0;i<=24;i++)
            t[i]=0;
        sum=n;
        for(int i=0;i<n;i++)
        {
            int x;
            scanf("%d",&x);
            t[x+1]++;
        }
        bool flag=false;
        int left=0,right=2*sum,mid;
        while(left<right)
        {
            mid=(left+right)/2;
            for(int i=0;i<25;i++)
                first[i]=-1;
            //s[i+1]-s[i]>=0
            for(int i=0;i<24;i++)
            {
                arc[i].v=i+1;
                arc[i].weight=0;
                arc[i].next=first[i];
                first[i]=i;
            }
            m=24;
            //s[i+1]-s[i]<=t[i+1] ( s[i]-s[i+1]>=-t[i+1] )
            for(int i=0;i<24;i++)
            {
                arc[m].v=i;
                arc[m].weight=-t[i+1];
                arc[m].next=first[i+1];
                first[i+1]=m++;
            }
            //s[24]-s[0]>=mid
            arc[m].v=24;
            arc[m].weight=mid;
            arc[m].next=first[0];
            first[0]=m++;
            for(int j=0;j<24;)
            {
                int i=(j+8)%24;
                i++;j++;
                arc[m].v=i;
                if(i>j)//i>j && j+8=i , s[i]-s[j]>=c[i]
                    arc[m].weight=c[i];
                else//i<j && i=(j+8)%24 , s[i]-s[j]>=c[i]-mid
                    arc[m].weight=c[i]-mid;
                arc[m].next=first[j];
                first[j]=m++;
            }
            arc[m].v=8;
            arc[m].next=first[0];
            first[0]=m;
            arc[m++].weight=c[8];
/*            for(int i=0;i<25;i++)
            {
                printf("%d:",i);
                for(int j=first[i];j!=-1;j=arc[j].next)
                    printf("%d,",arc[j].v);
                printf("\n");
            }
            getchar()*/;
            if(spfa(0))
                right=mid;
            else
                left=mid+1;
        }
        if(right<=n)
            printf("%d\n",right);
        else
            printf("No Solution\n");
    }
    return 0;
}

 

posted @ 2013-05-02 01:27  Hogg  阅读(442)  评论(0编辑  收藏  举报