记录编号 |
290266 |
评测结果 |
AAAAAAAAAA |
题目名称 |
[POJ1275]出纳员的雇佣 |
最终得分 |
100 |
用户昵称 |
Sky_miner |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.008 s |
提交时间 |
2016-08-06 06:08:40 |
内存使用 |
0.29 MiB |
显示代码纯文本
- /*
- 设num[ i ]为i时刻能够开始工作的人数,x[ i ]为 第 i 时刻实际雇佣的人数,那么x[ I ]<=num[ I ]。
- 设r[ i ](输入的每一时刻所需的人数)为i时刻至少需要工作的人数,于是有如下关系:
- x[ I-7 ]+x[ I-6 ]+x[ I-5 ]+x[ I-4 ]+x[ I-3 ]+x[ I-2 ]+x[ I-1 ]+x[ I ]>=r[ I ]
- 设s[ I ]=x[ 1 ]+x[ 2 ]…+x[ I ],得到
- 0<=s[ I ]-s[ I-1 ]<=num[ I ], 0<=I<=23
- s[ I ]-s[ I-8 ]>=r[ I ], 8<=I<=23 建立关系
- s[ 23 ]+s[ I ]-s[ I+16 ]>=r[ I ], 0<=I<=7 建立可以循环的关系
- 对于以上的几组不等式,我们采用一种非常笨拙的办法处理这一系列的不等式(其实也是让零乱的式子变得更加整齐,易于处理)。
- 首先我们要明白差分约束系统的应用对象(它通常针对多个二项相减的不等式的)
- 于是我们将上面的所有式子都转化成两项未知项在左边,另外的常数项在右边,且中间用>=连接的式子,即:
- s[ I ] - s[ I-1 ] >= 0 (0<=I<=23)
- s[ I-1 ] - s[ I ] >= -num[ I ] (0<=I<=23)
- s[ I ]-s[ I-8 ]>=r[ I ] (8<=I<=23)
- s[ I ]-s[ I+16 ]>=r[ I ]-s[ 23 ] (0<=I<= 7)
- S[23] - 0 >= sum;sum为雇佣的出纳员总数
- */
- //好麻烦的关系转换,,,对差分约束不会再有爱了。。。
- #include <cstdio>
- #include <cstring>
- using namespace std;
- template<typename T>inline void read(T &x){
- x=0;char ch;bool flag = false;
- while(ch=getchar(),ch<'!'); if( ch == '-' ) ch=getchar(),flag = true;
- while(x=10*x+ch-'0',ch=getchar(),ch>'!');if( flag ) x=-x;
- }
- int n,m,p,ecnt,T;
- int dis[30],cnt[30],r[30],t[30];
- const int INF = 1e9;
- int to[100],head[30],he[30],ne[100]={0},w[100]={0};
- inline void add(int u,int v,int c){
- to[++ecnt] = v;
- w[ecnt] = c;
- ne[ecnt] = head[u];
- head[u] = ecnt;
- }
- int Q[100],qhead = 1,qtail = 99,size = 0;
- bool flag[100];
- inline int top(){
- int x = Q[qhead];
- if( ++qhead == 100 )qhead=1;
- --size;
- flag[x] = false;
- return x;
- }
- inline void push_front(int x){
- flag[x] = true;
- ++size;
- if( !(--qhead) ) qhead=99;
- Q[ qhead ] = x;
- }
- inline void push_back(int x){
- flag[x] = true;
- ++size;
- if(++qtail == 100) qtail = 1;
- Q[qtail] = x;
- }
- inline bool spfa(int mid){
- for(int i = 0;i <= 24; ++i) dis[i] = -INF,cnt[i] = 0;
- cnt[0] = 1;dis[0] = 0;
- push_back(0);
- while( size ) for(int x=top(),i=head[x];i;i=ne[i])
- if( dis[ to[i] ] < dis[x] + w[i]){
- dis[ to[i] ] = dis[x] + w[i];
- if( !flag[to[i]] ){
- if( ++cnt[to[i]] > 24) return 0;
- if( size && dis[Q[qhead]] <= dis[to[i]]) push_front(to[i]);
- else push_back(to[i]);
- }
- }
- if(dis[24] == mid) return 1;
- return 0;
- }
-
- int main(){
- freopen("cashieremployment.in","r",stdin);
- freopen("cashieremployment.out","w",stdout);
- read<int>(T);
- while(T--){
- for(int i=1;i<=24;++i) read<int>(r[i]);
- for(int i=0;i<=24;++i) t[i] = head[i] = 0;
- read<int>(n);
- ecnt = 0;
- int x;
- for(int i=1;i<=n;++i) read<int>(x),t[x+1]++;
- for(int i=1;i<=24;++i) add(i-1,i,0),add(i,i-1,-t[i]);
- for(int i=0;i<=24;++i) he[i] = head[i];
- int ans = -1,L = 0,R = n;
- while(L<=R){
- int mid = (L+R)>>1;ecnt=48;
- for(int i=0;i<=24;++i)head[i]=he[i];
- add(0,24,mid);
- for(int i=1;i<=8;++i)add(i+16,i,r[i]-mid);
- for(int i=9;i<=24;++i)add(i-8,i,r[i]);
- if(spfa(mid)) ans = mid,R = mid-1;
- else L=mid+1;
- }
- if(ans == -1) printf("No Solution\n");
- else printf("%d\n",ans);
- }
- return 0;
- }