poj 1275 Cashier Employment

好长的一道差分约束啊 啊 啊!

戳戳戳

题意:
德黑兰的一家每天24小时营业的超市,需要一批出纳员来满足它的需求。超市经理雇佣你来帮他解决一个问题————超市在每天的不同时段需要不同数目的出纳员(例如,午夜只需一小批,而下午则需要很多)来为顾客提供优质服务,他希望雇佣最少数目的纳员。
超市经历已经提供一天里每一小时需要出纳员的最少数量————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,它们都是非负整数,计算为满足上述限制需要雇佣的最少出纳员数目、在每一时刻可以有比对应R(i)更多的出纳员在工作
输入描述:
输入文件的第1行为一个整数T,表示输入文件中测试数据的数目(至多20个)。每个测试数据第一行为24个整数,表示R(0),R(1),…,R(23),R(i)最大可以取到1000。接下来一行是一个整数N,表示申请者的数目,0<=N<=1000。接下来有N行,每行为一个整数ti,0<=ti<=23,测试数据之间没有空行。
输出描述:
对输入文件中的每个测试数据,输出占一行,为需要雇佣的出纳员的最少数目。如果某个测试数据没有解。则输出”No Solution”。

思路:
没有思路。。。。。。。
所以 看了题解

然后 列出不等式 5个
其中 need【i】 表示第i个小时 需要的人
x[i]表示 申请的人

所以 我们要 求 的 ans 其实是 s[i](从0到i时刻 需要的人) 中的s[24]
【【这里 po主 是 第几个小时 所以 从1开始的哦】】 这样的话s[0]=0十分好用了

那么 5个狮子是什么呢

1、s[i]-s[i-1]>=0
2. s[i]-s[i-1]<=have[i]–>s[i-1]-s[i]>=-have[i]
3. s[i]-s[i-8]>=need[i] (9<=i<=24) 【【这个狮子不理解? 其实s【i】表示的是 从0到i时刻 正在 工作的 人 也就是 每个小时开始工作的人a[i]+a[i-1]+a[i-2]++++a[i-7] 表示的是8个小时的工作时间吗 不就是s[i]-s[i-8]】】
4. s[i]-s[i+16]>=need[i]-s24 隔天啊

5.隐藏大boss s[24]-s[0]>=ans 好难想啊 不加会错 亲测/(ㄒoㄒ)/~~

中间 spfa最长路 写错了,顺手加深了一下 理解 挺好

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
//by mars_ch
int need[31];//至少需要的人数
int x[31];//申请的人数
int s[31];//x的前缀和 
int n,tot,res;
int dis[31];
int inq[31];
int cnt[31];
struct data
{
    int f,t,w;
    int nxt;
}e[400005];
int first[10005];
void add(int a,int b,int c)
{
    e[++tot].f=a;
    e[tot].t=b;
    e[tot].w=c;
    e[tot].nxt=first[a];
    first[a]=tot;
}
void build(int ans)
{
    memset(first,-1,sizeof(first));
    tot=0;
    add(0,24,ans);
    for(int i=1;i<=24;i++)
    {
        add(i-1,i,0);     //约束条件 s[i]-s[i-1]]>=0 
        add(i,i-1,-x[i]);   //s[i-1]-s[i]>=-have[i];
    }
    for(int i=9;i<=24;i++)
    {
        add(i-8,i,need[i]);   //s[i]-s[i-8]>=need[i]
    }
    for(int i=1;i<=8;i++)
    {
        add(i+16,i,need[i]-ans);   //s[i]-s[i+16]>=need[i]-ans;
    } 
}
bool spfa(int ans)
{
    memset(inq,0,sizeof(inq));
    memset(dis,-127,sizeof(dis));
    memset(cnt,0,sizeof(cnt));
    queue<int> q;
    while(!q.empty()) q.pop();
    q.push(0);
    dis[0]=0;
    inq[0]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=first[u];i!=-1;i=e[i].nxt)
        {
            int v=e[i].t;
            if(dis[v]<dis[u]+e[i].w)
            {
                dis[v]=dis[u]+e[i].w;
                if(!inq[v])
                {
                    inq[v]=1;
                    q.push(v);
                    if(++cnt[v] > 24)
                    {
                        return false;
                    }
                }
            }
        }
        inq[u]=0;
    }
    if(dis[24]>=ans)
    {
        return true;
    }
    else return false;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        /***************init***********/ 
        bool flag=false;
        memset(first,-1,sizeof(first));
        tot=0;
        memset(x,0,sizeof(x));
        /***********input*************/ 
        for(int i=1;i<=24;i++)
        {
            scanf("%d",&need[i]);
        }
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int a;
            scanf("%d",&a);
            x[a+1]++;
        }
        for(int i=0;i<=n;i++)
        {
            build(i);
            if(spfa(i))
            {
                printf("%d\n",i);
                flag=true;
            }
            if(flag) break;
        } 
        if(!flag)
        {
            printf("No Solution\n");
        }
     } 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值