poj 1275 Cashier Employment 差分约束

#include <bits/stdc++.h>
using namespace std;
#define ULL unsigned long long
#define LL long long
const LL mod=998244353;
const int maxn=20+10;
const int n=24;
int r[maxn];
int b[maxn];
struct edge{int u,v,w;};
vector<edge>e;
void addedge(int u,int v,int w)
{
   e.push_back((edge){u,v,w});
}
//d_i 前i小时一共需要雇佣的人数
//b_i 第i小时开始时可以上班的人数
//r_i 第i小时需要工作的人数
// d_(i-1)-d_i<=0  d_i递增
// d_i-d_(i-1)<=b_i 第i小时雇佣的人应小于该小时能开始上班的人数
// d_(i-8)-d_i<=-r_i 每8个小时段一共开始上班的人数满足第i个小时的需求
// d_(i+16)-d_i<=limit-r_i  同上,该超市是[每天]24小时营业
// d_0-d_24<=-limit

int dis[maxn];
#define u (i.u)
#define v (i.v)
#define w (i.w)
int spfa(int val)
{
    e.clear();
    for(int i=1;i<=n;i++)
        addedge(i,i-1,0),addedge(i-1,i,b[i]);
    for(int i=9;i<=24;i++)
        addedge(i,i-8,-r[i]);
    for(int i=1;i<=8;i++)
        addedge(i,i+16,val-r[i]);
//    addedge(0,24,val);
    addedge(24,0,-val);
    memset(dis,0x3f,sizeof dis);dis[0]=0;
    for(int i=1;i<n;i++)
        for(auto& i:e) dis[v]=min(dis[u]+w,dis[v]);
    for(auto& i:e) if(dis[v]>dis[u]+w) return false;
//    printf("%d %d %d\n",dis[0],dis[24],-val);
    return true;
}
#undef u
#undef v
#undef w
int main()
{
#ifdef shuaishuai
    freopen("in.txt","r",stdin);
//    freopen("in.out","w",stdout);
#endif // shuaishuai
    int t;
    scanf("%d",&t);
    while(t--)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",r+i);
            b[i]=0;
        }
        int m;
        scanf("%d",&m);
        for(int i=0,x;i<m;i++)
        {
            scanf("%d",&x);b[x+1]++;
        }
        int res=-1,l=0,r=m,mid;
        while(l<=r)
        {
            mid=(l+r)/2;
            if(spfa(mid)) r=mid-1,res=mid;
            else l=mid+1;
        }
        if(res==-1) puts("No Solution");
        else printf("%d\n",res);
//        int i;
//        for(i=0;i<=m;i++)
//            if(spfa(i)) break;
//        if(i<=m) printf("%d\n",i);
//        else puts("No Solution");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/polya/p/9932084.html