POJ-1275 Cashier Employment
题目链接:
https://vjudge.net/problem/POJ-1275
题意:
对于0到23、总共24个时刻,每个时刻至少需要r[i]个人,现在有m个人应聘,每个人开始的工作时间为t[i],且每个人都要工作八小时,求需要的最少人数。
分析:
为了方便,不妨对每个时刻加一,将0到23变为1到24。设s[i]为从0时刻到i时刻的总人数,num[i]为从i时刻开始工作的人数,那么根据题意可以得到以下不等式:
(由于求最小值,这里所有不等式写成A-B>=c的形式)
(1)s[i]-s[i-1]>=0(s单调递增)
(2)s[i-1]-s[i]>=-num[i](i时刻新增的人数不大于从i时刻开始工作的人数)
(3)如果i>=8,那么有s[i]-s[i-8]>=r[i](从i-7到i时刻的总人数要不小于r[i])
(4)如果i<8,那么有s[i]-s[i+16]>=r[i]-s[24](通过变形容易知道)
(5)s[24]-s[0]>=s[24]
(6)s[0]-s[24]>=-s[24](s[24]是一个待枚举的定值,且s[0]=0,将s[24]-s[0]=s[24]变为两条不等式)
以0为超级源点,由前两条不等式保证从0能到达所有顶点。从1到m升序枚举s[24],根据以上不等式建图,判断是否有负环。如果没有负环说明存在一组可行解,输出当前枚举到的值。如果枚举完都不存在解,输出No Solution。
代码(这里用的是bellman-ford判断负环。spfa?它死了):
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <vector> 5 #include <queue> 6 #include <map> 7 #include <set> 8 #include <cstring> 9 const int INF=0x3f3f3f3f; 10 using namespace std; 11 struct edge 12 { 13 int u,v,w; 14 }e[10000]; 15 int t,m,cnt,r[25],num[25],dis[25]; 16 void add(int u,int v,int w) 17 { 18 ++cnt; 19 e[cnt].u=u; 20 e[cnt].v=v; 21 e[cnt].w=w; 22 } 23 bool bellman_ford(int k) 24 { 25 memset(dis,-INF,sizeof(dis)); 26 cnt=0; 27 dis[0]=0; 28 for(int i=1;i<=24;++i) 29 { 30 add(i-1,i,0); 31 add(i,i-1,-num[i]); 32 if(i>=8)add(i-8,i,r[i]); 33 else add(i+16,i,r[i]-k); 34 } 35 add(0,24,k); 36 add(24,0,-k); 37 int i,j; 38 for(i=1;i<=25;++i) 39 { 40 int flag=0; 41 for(j=1;j<=cnt;++j) 42 { 43 if(dis[e[j].v]<dis[e[j].u]+e[j].w) 44 { 45 dis[e[j].v]=dis[e[j].u]+e[j].w; 46 flag=1; 47 } 48 } 49 if(!flag)break; 50 } 51 return i<26; 52 } 53 void solve() 54 { 55 for(int i=1;i<=m;++i) 56 { 57 if(bellman_ford(i)) 58 { 59 printf("%d\n",i); 60 return; 61 } 62 } 63 printf("No Solution\n"); 64 return; 65 } 66 int main(void) 67 { 68 scanf("%d",&t); 69 while(t--) 70 { 71 for(int i=1;i<=24;++i)scanf("%d",&r[i]); 72 scanf("%d",&m); 73 memset(num,0,sizeof(num)); 74 for(int i=1;i<=m;++i) 75 { 76 int x; 77 scanf("%d",&x); 78 ++num[x+1]; 79 } 80 solve(); 81 } 82 return 0; 83 }
时间复杂度:O(tm),其中m为应聘的人数。实际上最坏情况下需要跑m遍bellman-ford,而bellman-ford的时间复杂度为O(VE),V为图的顶点数,E为图的边数。但在本题中V=25,E=O(V),O(VE)为常数级,从而使整体的复杂度由O(tmVE)变为O(tm)。
空间复杂度:O(1),所有存储空间都有不随任何变量变化的常数上界。