POJ1275-Cashier Employment【差分约束系统】
正題
題目鏈接:http://poj.org/problem?id=1275
題目大意
1~241\sim 241~24小時中第iii個小時需要rir_iri?個出納員
有nnn個人應聘,第iii從xix_ixi?開始工作,一直工作8個小時。
求至少要招募多少人應聘。
解題思路
numinum_inumi?表示第iii個小時有多少人招聘。
設定kik_iki?表示第iii個小時放多少人
這時需要ki≥rIk_i\geq r_Iki?≥rI?且∑i=07num(n?i+24)%24+1≤ki\sum_{i=0}^7num_{(n-i+24)\%24+1}\leq k_i∑i=07?num(n?i+24)%24+1?≤ki?
這時我們要設定差分約束si=∑i=1isis_i=\sum_{i=1}^is_isi?=∑i=1i?si?
然后得出
si?si?1≥0s_i-s_{i-1}\geq 0si??si?1?≥0
si?1?si≥?numis_{i-1}-s_i\geq -num_isi?1??si?≥?numi?
si?si?8≥ris_i-s_{i-8}\geq r_isi??si?8?≥ri?
si?si+16≥ri?s24s_i-s_{i+16}\geq r_i-s_{24}si??si+16?≥ri??s24?
然后因為最后一個式子有三個未知量,所以我們枚舉s24s_{24}s24?就好了
codecodecode
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int N=30; struct edge{int to,next,w; }a[N*8]; queue<int> q; int T,n,tot; int r[N],f[N],cnt[N],num[N],ls[N]; bool v[N],flag; void addl(int x,int y,int w) {a[++tot].to=y;a[tot].w=w;a[tot].next=ls[x];ls[x]=tot; } void build(int x) {tot=0;memset(ls,0,sizeof(ls));addl(0,24,x);for(int i=1;i<=24;i++){addl(i-1,i,0);addl(i,i-1,-num[i]);if(i>=8) addl(i-8,i,r[i]);else addl(i+16,i,r[i]-x);} } int spfa(int ans) {memset(f,0xcf,sizeof(f));memset(cnt,0,sizeof(cnt));memset(v,0,sizeof(v));while(!q.empty()) q.pop();q.push(0);f[0]=0;v[0]=1;while(!q.empty()){int x=q.front();v[x]=0;q.pop();for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(f[x]+a[i].w>f[y]){f[y]=f[x]+a[i].w;if(!v[y]){q.push(y);v[y]=1;}if(++cnt[y]>24)return 0;}}}if(f[24]==ans) return 1;return 0; } int main() {scanf("%d",&T);while(T--){memset(num,0,sizeof(num));for(int i=1;i<=24;i++)scanf("%d",&r[i]);scanf("%d",&n);for(int i=1;i<=n;i++){int x;scanf("%d",&x);num[x+1]++;}flag=0;for(int i=0;i<=n;i++){build(i);if(spfa(i)){flag=true;printf("%d",i);break;}}if(!flag) printf("No Solution");putchar('\n');} } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的POJ1275-Cashier Employment【差分约束系统】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P1081-开车旅行【倍增,链表,dp】
- 下一篇: 大年初一祝福语