EOJ:Museum Guards

Museum Guards

Time Limit: 5000MS Memory Limit: 65536K
Total Submits: 38 Accepted: 17

Description

A museum has hired some guards and is trying to build a schedule for them. The museum would like to build a 24-hour schedule for the guards, such that:
  • Each guard works during the same time intervals every day.
  • Each guard works within his/her time windows of availability, which s/he specifies.
  • Each guard works at most the amount of time s/he is able, which s/he also specifies.
  • The guards can only shift (start or stop working) on half hour boundaries. (e.g. 04:00 or 04:30, but not 04:15).
  • The guards are only scheduled for shifts if they are available to work at all times during those shifts. (e.g. if a guard‟s window of availability opens at 03:05, they cannot be scheduled at 03:00.)
  • The minimum number of guards on duty at any time during the day is maximized. This improves security of the museum.

Write a program to help the museum staff determine the maximum number of guards that they can maintain at all times throughout a 24-hour day, given the constraints of the guards‟ availability. You may assume that guard exchanges are instantaneous. That is, if 2 guards leave and 2 other guards arrive at the same time, the museum is guarded by 2 guards through this exchange.

 

Input

There will be multiple test cases. Each test case begins with a line containing a single integer N (1 ≤ N ≤ 50), the number of guards available. There will then be N blocks of data, one for each guard.
Each block provides the preferences of one guard. A block begins with two integers, K (1 ≤ K ≤ 50) and M (1 ≤ M ≤ 1440), in that order; K is the number of time intervals specifying when the guard is available for work, and M is the maximum number of minutes s/he is able to work each day. The next K lines each contains the starting and ending time, in that order, of a time interval where the guard is available, separated by whitespace. These time intervals may overlap. The union of all K time intervals provides the complete set of times at which the guard is available.
A starting or ending time is formatted as HH:MM (00 ≤ HH ≤ 23, 00 ≤ MM ≤ 59). Midnight is represented by 00:00. When the ending time is smaller than the starting time, it means the guard is available for working past midnight. For example, the interval “23:00 03:00” means the guard is available from 11pm at night to 3am in the morning. If the starting and ending times are equal, then the guard is available for work during any time intervals throughout the day. The last test case is followed by a line with a single 0.

 

Output

For each test case, output a single integer, representing the minimum number of guards on duty at any given time during the day, using a schedule that maximizes this value. That is, output the largest integer k, such that there is a schedule where at any given moment, there are k guards on duty at the museum, assuming instantaneous exchanges specified above. Do not print any blank lines between answers.

 

Sample Input

3
1 540
00:00 00:00
3 480
08:00 10:00
09:00 12:00
13:00 19:00
1 420
17:00 00:00
5
1 720
18:00 12:00
1 1080
00:00 23:00
1 1080
00:00 20:00
1 1050
06:00 00:00
1 360
18:00 00:00
3
1 1440
00:00 00:00
1 720
00:00 12:15
1 720
12:05 00:15
0

 

Sample Output

1
2
1

 

Source

__________________________________________________________________________________________________
题解:
这题我调了四天!
题目中说守卫只能在整点或者整半点的时候交换工作,这是一个很明显的暗示(可惜比赛当时没看出来)
将每个守卫看成点,一天二十四个小时,分成48个点,如果一个守卫能在某半个小时连线,就将其与该半个小时的点连条线。
再添加一个源点,与每个守卫连线,权值就是守卫总共能工作的时间,添加一个汇点,与每半个小时连线。
这样就是一个最大流问题,最大流有很多中解决方法,四天中有两天就是为了调那个ISAP算法……
但是仔细想想,会出现一个问题:
假设时间点到汇点的权值无穷大,如果守卫一能在00:30和1:00工作,守卫二也能在00:30和1:00工作,那么守卫一和守卫二在同时在00:30和守卫在00:30,守卫二在1:00工作的最大流是一样的,但题目要求使得一天二十四小时都有警卫工作。所以我们需要枚举时间点到汇点的权值,做N次最大流。
另外还有一个需要注意的地方,源点到守卫点的权值要设为T/30,而守卫点到时间点的权值为1。为了这个我调了一个晚上……如果权值设为分钟数,守卫点到时间点的权值为30的话,那么可能出现守卫在一个时间点工作小于30分钟的情况。
代码
1 #include<stdio.h>
2 #include<memory.h>
3 #include<stdlib.h>
4  #define maxn 102
5  int d[maxn],g[maxn][maxn],f[maxn][maxn],pre[maxn],map[maxn][maxn],sum[maxn],current[maxn];
6  int n,m,num,mm;
7  struct node
8 {
9 int x,y;
10 }seg[1000],time[1000];
11  #define oo 0xfffffff
12  int cmp(const void *a,const void *b)
13 {
14 struct node *va=(struct node*)a;
15 struct node *vb=(struct node*)b;
16 return va->x-vb->x;
17 }
18  void rev_bfs(int t)
19 {
20 int queue[maxn],flag[maxn];
21 int head,tail,i;
22 memset(sum,0,sizeof(sum));
23 for (i=0;i<=n+49;i++)
24 {
25 d[i]=n+49;
26 sum[n+49]++;
27 }
28 sum[n+49]--;
29 sum[0]++;
30 d[t]=0;
31 queue[1]=t;
32 flag[t]=1;
33 head=1;tail=1;
34 memset(flag,0,sizeof(flag));
35 while (head<=tail)
36 {
37 for (i=0;i<=n+49;i++)
38 if (flag[i]==0&&g[i][queue[head]]>0)
39 {
40 queue[++tail]=i;
41 d[i]=d[queue[head]]+1;
42 sum[n+49]--;
43 sum[d[i]]++;
44 flag[i]=1;
45 }
46 head++;
47 }
48 }
49  void augment(int s,int t)
50 {
51 int i,min;
52 min=oo;
53 for (i=t;i!=s;i=pre[i])
54 if (g[pre[i]][i]<min)
55 min=g[pre[i]][i];
56 for (i=t;i!=s;i=pre[i])
57 {
58 g[pre[i]][i]-=min;;
59 g[i][pre[i]]+=min;
60 f[pre[i]][i]+=min;
61 f[i][pre[i]]-=min;
62 }
63 }
64  int retreat(int *u,int s)
65 {
66 int v,min;
67 min=n+49;
68 for (v=0;v<=n+49;v++)
69 if (g[*u][v]>0&&d[v]<min)
70 min=d[v];
71 sum[d[*u]]--;
72 if ((sum[d[*u]])==0&&d[*u]<=n+49) return 0;
73 d[*u]=min+1;
74 sum[d[*u]]++;
75 current[*u]=0;
76 if (*u!=s) *u=pre[*u];
77 return 1;
78 }
79  void ISAP(int s,int t)
80 {
81 int u,v;
82 rev_bfs(t);
83 u=s;
84 while (d[s]<n+50)
85 {
86 for (v=current[u];v<=n+49;v++)
87 if (g[u][v]>0&&d[u]==d[v]+1)
88 break;
89 if (v<=n+49)
90 {
91 current[u]=v;
92 pre[v]=u;
93 u=v;
94 if (u==t)
95 {
96 augment(s,t);
97 u=s;
98 }
99 }
100 else if (retreat(&u,s)==0) return;
101 }
102 }
103 void init()
104 {
105 int i,j,a,b,c,d,min,t,k,ans,max,st,en,temp;
106 while (scanf("%d",&n)!=EOF&&n)
107 {
108 memset(map,0,sizeof(map));;
109 for (i=1;i<=n;i++)
110 {
111 scanf("%d%d",&m,&t);
112 map[48][i+48]=t/30;
113 num=0;
114 mm=0;
115 for (j=1;j<=m;j++)
116 {
117 scanf("%d:%d %d:%d",&a,&b,&c,&d);
118 if (a==c&&b==d)
119 {
120 for (k=0;k<48;k++)
121 map[i+48][k]=1;
122 continue;
123 }
124 if (c==0&&d==0)
125 {
126 num++;
127 seg[num].x=a*60+b;
128 seg[num].y=1440;
129 }
130 else if (a*60+b>c*60+d)
131 {
132 num++;
133 seg[num].x=a*60+b;
134 seg[num].y=1440;
135 num++;
136 seg[num].x=0;
137 seg[num].y=c*60+d;
138 }
139 else
140 {
141 num++;
142 seg[num].x=a*60+b;
143 seg[num].y=c*60+d;
144 }
145 }
146 if (num==0) continue;
147 qsort(seg+1,num,sizeof(seg[1]),cmp);
148 st=seg[1].x;en=seg[1].y;
149 seg[num+1].x=1500;seg[num+1].y=1600;
150 for (j=2;j<=num+1;j++)
151 {
152 a=seg[j].x;
153 b=seg[j].y;
154 if (st<=a&&a<=en&&en<b)
155 en=b;
156 else if (a>en)
157 {
158 mm++;
159 time[mm].x=st;
160 time[mm].y=en;
161 st=a;
162 en=b;
163 }
164 }
165 for (j=1;j<=mm;j++)
166 {
167 a=time[j].x/60;
168 b=time[j].x-60*a;
169 c=time[j].y/60;
170 d=time[j].y-60*c;
171 if (a==c)
172 {
173 if (b==0&&d>=30)
174 map[i+48][a*2]=1;
175 }
176 else
177 {
178 if (b>0&&b<=30) b=30;
179 if (b>30)
180 {
181 a++;
182 b=0;
183 }
184 if (d<30) d=0;
185 if (d>30) d=30;
186 while (a!=c||b!=d)
187 {
188 map[i+48][a*2+b/30]=1;
189 b+=30;
190 if (b==60)
191 {
192 a++;
193 b=0;
194 }
195 }
196 }
197 }
198 }
199 max=oo;
200 for (j=0;j<48;j++)
201 {
202 temp=0;
203 for (k=49;k<n+49;k++)
204 if (map[k][j]>0) temp++;
205 if (temp<max)
206 max=temp;
207 }
208 ans=0;
209 for (j=1;j<=max;j++)
210 {
211 memset(g,0,sizeof(g));
212 memset(f,0,sizeof(f));
213 memset(current,0,sizeof(current));
214 for (i=0;i<=49+n;i++)
215 for (k=0;k<=49+n;k++)
216 g[i][k]=map[i][k];
217 for (i=0;i<48;i++)
218 g[i][n+49]=j;
219 ISAP(48,n+49);
220 min=oo;
221 for (i=0;i<48;i++)
222 if (f[i][n+49]<min)
223 min=f[i][n+49];
224 if (min>ans) ans=min;
225 }
226 printf("%d\n",ans);
227 }
228 }
229 int main()
230 {
231 freopen("a.txt","r",stdin);
232 //freopen("b.txt","w",stdout);
233 init();
234 return 0;
235 }

 

posted on 2010-08-05 22:23  风也轻云也淡  阅读(543)  评论(0编辑  收藏  举报