【刷题】【差分约束】出纳员问题

调了一下午,已经没有力气写题解了,

wa点已经标出来了,

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
int n,x;
const int N=28,M=120;
int nd[N],c[N];

int tot,head[N];
int ev[M],ew[M],enx[M];
void add(int u,int v,int w)
{ ev[++tot]=v,ew[tot]=w,enx[tot]=head[u],head[u]=tot; }
void build(int as)
{
    tot=0;
    memset(head,0,sizeof(head));
    add(0,24,as);
    
    for(int i=1;i<=24;i++)
    {
        add(i-1,i,0);
        add(i,i-1,-c[i]);
        if(i>=9) add(i-8,i,nd[i]);
        if(i<=8) add(i+16,i,nd[i]-as);
    }
}

int dis[N],tm[N];
bool in[N];
bool spfa(int mx)
{
    build(mx);
    memset(dis,0x80,sizeof(dis));
    memset(in,false,sizeof(in));
    memset(tm,0,sizeof(tm));
    
    queue <int> q;
    while(!q.empty() ) q.pop() ;
    q.push(0);dis[0]=0;
    int cnt=-1;
    while(!q.empty() && dis[24]<=mx)
    {
        int t=q.front() ;q.pop() ;
        for(int i=head[t];i;i=enx[i])
        {
            int nx=ev[i];
            if(dis[nx]<dis[t]+ew[i])
            {
                dis[nx]=dis[t]+ew[i];
                if(++tm[nx]>=25)
                    return false;
                if(!in[nx])
                    in[nx]=true,q.push(nx); 
            }
        }
        in[t]=false;
    }
    return dis[24]==mx;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        for(int i=1;i<=24;i++)
            scanf("%d",&nd[i]);//nd[i]表示i-1 ~ i需要的人数 
        memset(c,0,sizeof(c));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&x),c[x+1]++;//x 开始投入工作 第一次工作在x-x+1,就是c[x+1] 
        
        int ans=n+1;
        for(int i=0;i<=n;i++)
            if(spfa(i))
            {
                ans=i;
                break;
            }
        if(ans>n) printf("No Solution\n");
        else printf("%d\n",ans);
    }
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xwww666666/p/11715163.html