poj 1275 Cashier Employment (差分约束)

  1 /*

  2 又是一道差分约束题,通过这道题让我更加理解了差分约束。

  3 差分约束的关键是 要充分利用所给条件

  4 建立数组的 逻辑意义 如此题的dis[]数组(s[]数组) 建立差分约束系统即(找出差分约束关系),

  5 

  6 

  7 

  
   
     

注:看了2006冯威的论文。整理如下:

设num[ i ]为i时刻能够开始工作的人数,x[ i ]为实际雇佣的人数, 设r[ i ]为i时刻至少需要工作的人数, s[ I ]=x[ 1 ]+x[ 2 ]…+x[ I ]

有如下关系:

x[ I ]<=num[ 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 ]

0<=s[ I ]-s[ I-1 ]<=num[ I ], 1<=I<=24
s[I]-s[ I-8 ]>=r[ I ], 8<=I<=24
s[ I ]-s[ I+16 ]>=r[ I ]-sum, 1<=I<=7

s[0]=0

s[24]-s[0]>=sum(冯威的论文少了这个条件,看了别人的解题报告,才发现。想想也是,sum是枚举的当前最小值,s[24]是实际工作的工人,那么其一定大于sum)

38 */ 39 40 #include<stdio.h> 41 #include<string.h> 42 #include<queue> 43 #include<iostream> 44 #define N 20000 45 #define max 0xfffffff 46 using namespace std; 47 struct node 48 { 49 int y; 50 int w; 51 int next; 52 }p[N*20]; 53 int next[N],num,vis[N],dis[N],time[N],n,a[N*3],t[N]; 54 queue<int>q; 55 void insert(int x,int y,int w) 56 { 57 p[num].y=y; 58 p[num].w=w; 59 p[num].next=next[x]; 60 next[x]=num; 61 num++; 62 } 63 void buildgragh(int x) 64 { 65 int i; 66 num=0; 67 memset(next,-1,sizeof(next)); 68 insert(0,24,x); 69 for(i=1;i<=24;i++) 70 { 71 insert(i-1,i,0); 72 insert(i,i-1,-t[i]); 73 } 74 for(i=1;i<=8;i++)insert(i+16,i,a[i]-x); 75 for(i=9;i<=24;i++)insert(i-8,i,a[i]); 76 77 78 79 } 80 int SPFA(int x) 81 { 82 int i; 83 memset(vis,0,sizeof(vis)); 84 memset(time,0,sizeof(time)); 85 86 for(i=0;i<=25;i++)dis[i]=-max; 87 dis[0]=0; 88 vis[0]=1; 89 time[0]=1; 90 while(!q.empty())q.pop(); 91 q.push(0); 92 93 while(!q.empty()) 94 { 95 96 int u=q.front(); 97 q.pop(); 98 vis[u]=0; 99 for(i=next[u];i!=-1;i=p[i].next) 100 { 101 102 int v=p[i].y; 103 104 if(dis[v]<dis[u]+p[i].w) 105 { 106 107 108 dis[v]=dis[u]+p[i].w; 109 if(!vis[v]) 110 { 111 vis[v]=1; 112 q.push(v); 113 114 time[v]++; 115 if(time[v]>24)return -1; 116 117 } 118 119 } 120 } 121 122 } 123 if(dis[24]==x)return 1; 124 else 125 return 0; 126 } 127 int main() 128 { 129 int T,i,s; 130 scanf("%d",&T); 131 132 while(T--) 133 { 134 135 memset(t,0,sizeof(t)); 136 for(i=1;i<=24;i++)scanf("%d",&a[i]); 137 scanf("%d",&n); 138 139 for(i=0;i<n;i++) 140 { 141 scanf("%d",&s); 142 t[s+1]++; 143 144 } 145 146 int f=0; 147 for(i=0;i<=n;i++) 148 { 149 buildgragh(i); 150 if(SPFA(i)>0) 151 { 152 f=1; 153 printf("%d\n",i); 154 break; 155 } 156 } 157 158 if(!f)printf("No Solution\n"); 159 160 161 } 162 }

你可能感兴趣的:(差分约束)