poj1275 Cashier Employment

被这道神仙的差分约束卡了两个小时。。。

对于约束条件真的要考虑的非常周全,并且这题是时间段,改段为点细节还是很多。

设s[i]表示0点~i点时间段要雇多少人

因为每一天需要的人手为c[i],有: s[i]-s[i-8]>=c[i] (1<=i<=8) 和 s[i]+s[24]-s[i-8]>=c[i] (9<=i<=24)

因为每一天至多雇t[i]个人,有: s[i]-s[i-1]<=t[i] 并且为了产生正环加入条件 s[i-1]-s[i]<=0

考虑二分s[24]的值,进行差分约束

为了控制s[24]的值只能为mid,有s[0]-s[24]<=mid 和 s[24]-s[0]>=mid

由于读入方式的不一样,题意人出现的时间段的编号是我定义的时间段编号-1(坑了我很久),要t[x+1]++;

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int c[30],t[30];
struct node
{
    int x,y,d,next;
}a[2100];int len,last[30];
void ins(int x,int y,int d)
{
    len++;
    a[len].x=x;a[len].y=y;a[len].d=d;
    a[len].next=last[x];last[x]=len;
}

int d[30],list[30];bool v[30];
bool check(int mid)
{
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=7;i++)ins(i+16,i,c[i]-mid);
    for(int i=8;i<=24;i++)ins(i-8,i,c[i]);
    for(int i=1;i<=24;i++)ins(i,i-1,-t[i]),ins(i-1,i,0);
    ins(24,0,-mid);ins(0,24,mid);
    
    memset(d,-63,sizeof(d));d[0]=0;
    memset(v,false,sizeof(v));v[0]=true;
    int head=1,tail=1;list[tail++]=0;
    while(head!=tail)
    {
        int x=list[head];
        if(x==24&&d[x]>mid)return false;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(d[y]<d[x]+a[k].d)
            {
                d[y]=d[x]+a[k].d;
                if(v[y]==false)
                {
                    v[y]=true;
                    list[tail++]=y;
                    if(tail==28)tail=1;
                }
            }
        }
        v[x]=false;
        head++;if(head==28)head=1;
    }
    return true;
}
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        for(int i=1;i<=24;i++)scanf("%d",&c[i]);
        int P,x;
        scanf("%d",&P);
        memset(t,0,sizeof(t));
        for(int i=1;i<=P;i++)
            scanf("%d",&x), t[x+1]++;
        
        int l=1,r=P,ans=-1;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(check(mid))
            {
                ans=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        if(ans==-1)printf("No Solution\n");
        else printf("%d\n",ans);
    }
    return 0;
}

 

 

 

posted @ 2018-08-28 20:55  AKCqhzdy  阅读(132)  评论(0编辑  收藏  举报