这道题很特殊,与以前做的差分约束完全不一样,因为在它的约束条件中竟然还有变量。
建图方法:
说明:
r[i]-------第i小时需要的人
t[i]-------第i小时去应聘的人
s[i]-------第0到i小时总共招聘的人
约束系统:
1.s[i]-s[i-1]<=t[i]
2.s[i]-s[i-1]>=0
3.s[j]-s[i]>=r[i],j=(i+8)%24,j>i
4.s[j]+sum-s[i]>=r[i],j=(i+8)%24,j<i
5.s[24]-s[0]>=sum
算法思想:Bellman_Ford()+枚举sum (此处也可以用二分枚举,我是直接枚举的)
#include<iostream> #include<cstdio> using namespace std; struct{ int u,v,w; }e[200]; int t[25],r[25],s[25],d[25]; int n,m; bool relax(int u,int v,int w) { if(d[u]+w>d[v]) { d[v]=d[u]+w; return true; } return false; } bool Bellman_Ford() { int i,j; bool flag=true; for(i=0;i<=n;i++) d[i]=100000000; d[0]=0; for(i=0;i<n&&flag;i++) { flag=false; for(j=0;j<m;j++) if(relax(e[j].u,e[j].v,e[j].w)) flag=true; } if(!flag) return true; for(j=0;j<m;j++) if(relax(e[j].u,e[j].v,e[j].w)) return false; return true; } int main() { int Case,sum; int i,j; scanf("%d",&Case); while(Case--) { for(i=1;i<=24;i++) { t[i]=0; scanf("%d",r+i); } scanf("%d",&n); while(n--) { int time; scanf("%d",&time); t[time+1]++; } for(i=1;i<=24;i++) s[i]=s[i-1]+t[i]; /////////////////////////// //此部分建固有边 m=0; n=24; for(i=1;i<=24;i++) { e[m].u=i-1; e[m].v=i; e[m].w=0; m++; e[m].u=i; e[m].v=i-1; e[m].w=-t[i]; m++; } for(i=1;i<=16;i++) { j=i+8; e[m].u=i; e[m].v=j; e[m].w=r[j]; m++; } ////////////////////////////// int mm=m; for(sum=0;sum<=s[24];sum++) { m=mm; for(i=17;i<=24;i++) { j=i-16; e[m].u=i; e[m].v=j; e[m].w=r[j]-sum; m++; } e[m].u=0; e[m].v=24; e[m].w=sum; m++; if(Bellman_Ford()) break; } if(sum<=s[24]) printf("%d\n",sum); else printf("No Solution\n"); } return 0; }