题意:有一个超市需要一些出纳员,已给出这个超市在各个时间段(0-1,1-2,2-3...共24个时间段)至少需要的出纳员数目,
现在前来应聘有n个人,每个人都有一个固定的开始工作的时间,这也意味着从这个时间开始他要连续工作8个小时。在满足这
个超市对出纳员的需求的前提下,让你求出最少雇佣的出纳员人数。
need[i]表示在第 i 个小时至少也要的人数,work[i]表示应聘者中可以在第i个小时开始工作的人数,s[i]表示前i个小时雇佣的人数,
x[ i ]表示第 i 个小时雇佣的人数。 s[i] - s[i - 1] = x[i]
约束条件:
(1) 0<= x[i] <= x[ i ] ,转化为 0 <= s[ i ] - s[i - 1] <= work[ i ]
(2) i >= 8 时:need[ i ] <= x[i] + x[i - 1] + x[i - 2] + x[i - 3] + x[i - 4] + x[i - 5] + x[i - 6] + x[i - 7]
转化为 need[ i ] <= s[ i ] - s[i - 8]
i < 8 时:s[ i ] +s[ 24 ] -s[16 + i] >= need[i] (不清楚的可以模拟一下)
(3)对上面的S[24]我们不知道它的值,但我们知道它表示前24个小时所雇用的总人数,也就是我们要求的结果sum.因此对于未知
的sum,我们需要从0到n枚举sum。需要再建一条边即:s[24] - s[0] >= sum
二分人数即可
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f #define INF 0x3f3f3f3f #define N 100000 int head[N]; int pos; struct node { int to,v,nex; }edge[N<<2]; void add(int a,int b,int c) { edge[++pos].nex=head[a]; head[a]=pos; edge[pos].v=c; edge[pos].to=b; } int n; int vis[N],dis[N],cnt[N]; int work[N],need[N]; void getmap(int k) { rep(i,1,24) { add(i-1,i,0); add(i,i-1,-work[i]); if(i>=8) add(i-8,i,need[i]); else add(16+i,i,need[i]-k); } add(0,24,k); } bool spfa(int k) { rep(i,1,24) vis[i]=0,dis[i]=-inf,cnt[i]=0; dis[0]=0; vis[0]=1; cnt[0]++; queue<int>q; q.push(0); while(!q.empty()) { int u=q.front();q.pop(); vis[u]=0; for(int i=head[u];i;i=edge[i].nex) { int v=edge[i].to; if(dis[v]<dis[u]+edge[i].v) { dis[v]=dis[u]+edge[i].v; if(!vis[v]) { if(++cnt[v]>24)return 0; vis[v]=1; q.push(v); } } } } return dis[24]==k; } int main() { int cas; RI(cas); while(cas--) { rep(i,1,24) RI(need[i]); CLR(work,0); int k;RI(k); rep(i,1,k) { int x;RI(x);work[x+1]++; } int L=0,R=k; int ans=-1; while(L<=R) { int mid=(L+R)>>1; pos=0;CLR(head,0); getmap(mid); if(!spfa(mid))L=mid+1; else R=mid-1,ans=mid; } if(ans!=-1) cout<<ans<<endl; else printf("No Solution "); } }