• 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
    ");
            else printf("%d
    ",ans);
        }
        return 0;
    }

     

  • 相关阅读:
    php根据时间显示刚刚,几分钟前,几小时前的实现代码
    PHP中获取当前页面的完整URL
    PhpExcel中文帮助手册|PhpExcel使用方法
    洛谷P1781 宇宙总统【排序+字符串】
    洛谷P1579 哥德巴赫猜想(升级版)【水题+素数】
    洛谷P1478 陶陶摘苹果(升级版)【水题】
    洛谷P1002 过河卒【dp】
    51Nod
    排序算法总结(C++)
    UVA1339
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9550773.html
Copyright © 2020-2023  润新知