出纳员问题

又一次不记得自己是怎么写的了...

Cashier Employment 出纳员问题
 
问题描述
    有一家24小时营业的超市,需要雇佣一批出纳员。一天中每个小时需要出纳员的最少数量为R0,R1,R2,...,R23。有N个人申请这项工作,每个申请者,从一个特定时刻Ti,开始连续工作恰好8个小时。(Ti为整数,且 0<=Ti<=23 )
    你的任务是计算出需要雇佣出纳员的最少数目,满足在每一时刻k,至少有Ri名出纳员在工作。
 
输入
第一行一个数T(T<=20),表示测试数据的个数。
对于每一个测试数据,第一行24个整数R0,R1,R2,...,R23,用空格分开。接下来的一行一个数N。然后接下来有N行,每一行有一个数Ti,表示第i个申请人在Ti时刻开始工作。
 
输出
对于每一个测试数据,仅包含一行,如果有答案,就输出最少出纳员的数目,反之则输出’ 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

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<algorithm>
  5 #include<queue>
  6 #define INF 0xfffffff
  7 using namespace std;
  8 struct list
  9 {
 10     int r;
 11     int len;
 12     int next;
 13 }node[500000];
 14 int head[100000];
 15 int r[10000];//需要人数
 16 int t[10000];//应征人数
 17 int num=0;
 18 int s[10000];//0-i雇佣人数
 19 int dist[10000];
 20 queue<int>q;
 21 void add(int x,int y,int z)
 22 {
 23     node[num].r=y;
 24     node[num].len=z;
 25     node[num].next=head[x];
 26     head[x]=num++;
 27 }
 28 void dos(int x)
 29 {
 30     int i;
 31     memset(head,-1,sizeof(head));
 32     add(0,24,x);
 33     for(i=1;i<=24;i++)
 34     {
 35         add(i-1,i,0);
 36         add(i,i-1,-t[i]);
 37     }
 38     for(i=1;i<=16;i++)
 39     {
 40         add(i,i+8,r[i+8]);
 41     }
 42     for(i=17;i<=24;i++)
 43     {
 44         add(i,i-16,r[i-16]-x);
 45     }
 46 }
 47 int spfa(int x)
 48 {
 49     int i;
 50     while(!q.empty())q.pop();
 51     for(i=0;i<=25;i++)dist[i]=-INF;
 52     dist[0]=0;
 53     q.push(0);
 54     int vis[100];
 55     int time[100];
 56     memset(time,0,sizeof(time));
 57     memset(vis,0,sizeof(vis));
 58     vis[0]=1;
 59     time[0]=1;
 60     while(!q.empty())
 61     {
 62         int e;
 63         e=q.front();
 64         q.pop();
 65         vis[e]=0;
 66         for(i=head[e];i!=-1;i=node[i].next)
 67         {
 68             int v=node[i].r;
 69             if(dist[v]<dist[e]+node[i].len)
 70             {
 71                 dist[v]=dist[e]+node[i].len;
 72                 if(!vis[v])
 73                 {
 74                     vis[v]=1;
 75                     q.push(v);
 76                     time[v]++;
 77                     if(time[v]>24)return -1;
 78                 }
 79             }
 80         }
 81     }
 82     if(dist[24]==x)return 1;
 83     else return 0;
 84 }
 85 int main()
 86 {
 87     int T,i,n,x;
 88     scanf("%d",&T);
 89     while(T--)
 90     {
 91         memset(r,0,sizeof(r));
 92         memset(t,0,sizeof(t));
 93         for(i=1;i<=24;i++)
 94         {
 95             scanf("%d",&r[i]);
 96         }
 97         scanf("%d",&n);
 98         for(i=0;i<n;i++)
 99         {
100             scanf("%d",&x);
101             t[x+1]++;
102         }
103         for(i=0;i<=n;i++)
104         {
105             dos(i);
106             if(spfa(i)>0)
107             {
108                 printf("%d\n",i);
109                 break;
110             }
111         }
112         if(i==n+1)
113         {
114             printf("No Solution\n");
115         }
116     }
117     return 0;
118 }

 

转载于:https://www.cnblogs.com/GC-hahaha/p/9458567.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值