差分约束系统,出纳员的雇佣
来源:互联网 发布:棋牌刷分软件 编辑:程序博客网 时间:2024/05/19 19:40
Tehran的一家每天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)更多的出纳员在工作。
输入格式:
输入文件的第一行为测试点个数(<= 20)。每组测试数据的第一行为24个整数表示R(0),R(1),…, R(23)(R(I)<= 1000)。接下来一行是N,表示申请者数目(0 <= N <= 1000),接下来每行包含一个整数tI (0 <= tI <= 23)。两组测试数据之间没有空行。
输出格式:
对于每个测试点,输出只有一行,包含一个整数,表示需要出纳员的最少数目。如果无解,你应当输出“No Solution!”
样例输入:
1
1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
5
0
23
22
1
10
样例输出:
1
时间限制:
1s
空间限制:
512M
#include<bits/stdc++.h>using namespace std;int t[30],sum,r[30],vis[30];int dis[30];int ne[101],fir[101],val[101],to[101];bool inq[101];int n,m,AwD,cnt,tot;void init(){ n=m=cnt=0; for(int i=0;i<=25;i++) dis[i]=2e9; for(int i=0;i<=25;i++) r[i]=0; for(int i=0;i<=25;i++) t[i]=0; tot=0;}void add(int u,int v,int w){ ne[++cnt]=fir[u];fir[u]=cnt;val[cnt]=w;to[cnt]=v;}void set_up_picture(){ //人数不能为负!!!// add(1,25,sum); cnt=0; for(int i=0;i<=25;i++) fir[i]=0; for(int i=0;i<=25;i++) ne[i]=0; for(int i=0;i<=25;i++) val[i]=0; for(int i=0;i<=25;i++) to[i]=0; add(24,0,-sum); for(int i=0;i<=23;i++) add(i+1,i,0); for(int i=0;i<=23;i++) add(i,i+1,t[i]); for(int i=8;i<=24;i++) add(i,i-8,-r[i]); for(int i=1;i<=7;i++) add(i,i+16,sum-r[i]);}queue <int> q;bool SPFA(){ set_up_picture(); for(int i=0;i<=25;i++) dis[i]=2e9; for(int i=0;i<=25;i++) inq[i]=0; for(int i=0;i<=25;i++) vis[i]=0; while(!q.empty()) q.pop(); int i=24; { inq[i]=1;dis[i]=0;vis[i]++;q.push(i); } while(!q.empty()) { int index=q.front();inq[index]=0; q.pop(); for(int i=fir[index];i;i=ne[i]) { int v=to[i]; if(dis[v]>dis[index]+val[i]) { dis[v]=dis[index]+val[i]; if(!inq[v]) { inq[v]=1;vis[v]++;q.push(v);if(vis[v]>25) return 0; } } } } return dis[0]==-sum;//我们先令最后减最前大于等于sum,最后判他用sum够不够完成该任务。}int main(){ cin>>AwD; while(AwD--) { init(); for(int i=1;i<=24;i++) scanf("%d",&r[i]); scanf("%d",&n); for(int i=1;i<=n;i++) {scanf("%d",&m);t[m+1]++;tot++;} bool flag=0; for(sum=0;sum<=tot;sum++) { if(SPFA()) { flag=1; printf("%d\n",sum);break; } } if(!flag) puts("No Solution!"); }}
本题是差分约束系统的经典题,复杂度够,所以不用二分,本题务必重新手打,连边操作比较烦,我的SPFA是倒着来的,其实是可以正着来的,此时我们只需要赋dis[0]为0,跑最短路,判dis[24]是不是sum就可以过了。
- 差分约束系统,出纳员的雇佣
- POJ 1275 Cashier Employment 出纳员问题 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 【差分约束系统】
- 差分约束系统
- 差分约束系统
- 差分约束系统
- ##差分约束系统##
- 差分约束系统
- 差分约束系统
- 差分约束系统
- java设计模式:二、观察者模式
- JDK-lib
- 跨站脚本攻击XSS
- 关于Vue
- 2017.5.17 COCI2014/2015 Contest#5
- 差分约束系统,出纳员的雇佣
- Minimum Edit Distance POJ 3356 && 51Nod 1183
- spark性能调优--jvm调优
- XSS危害——session劫持
- Windows上搭建Kafka运行环境
- PHP 推荐排序
- 编程代码规范
- 跨站请求伪造CSRF
- 全桥驱动变压器漏感处理