POJ 1275 Cashier Employment(差分約束)
阿新 • • 發佈:2020-08-24
思路:
設 \(S_i\) 為前 \(i\) 個小時錄取的人數, \(num_i\) 為第 \(i\) 個小時應聘的人數,\(x_i\) 為第 \(i\) 個小時僱傭的人數,可得:
\[\begin{aligned}&(~1~)~~0\leq x_i\leq num_i=>0\leq S_i-S_{i-1}\leq num_i\\\\&(~2~)\begin{cases}S_i-S_{i-1}\geq R_i~(i\geq 8)\\S_i+S_{24}-S_{16+i}\geq R_i=>S_i-S_{16+i}~\geq R_i-S_{24}=R_i-sum(0< i<8)\end{cases}\\\\&(~3~)~~S_{24}-S_0\geq sum\end{aligned} \]
對於 \((3)\) 因為 \(S_{24}\) 我們不知道它的值,但是它表示的就是 \(sum\) 即答案,所以列舉 \(sum\) (可以二分列舉,我懶得寫了)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> #define maxn 100 #define INF 0x3f3f3f3f using namespace std; int N;//個應聘者 struct node { int u, v, w, next; }; node edge[200000]; int dist[maxn], head[maxn], used[maxn], cnt; bool vis[maxn]; int work[maxn];//work[i]表示在第 i 個小時開始工作的人數 int need[maxn];//應聘者中可以在第i個小時開始工作的人數 void init (){ cnt = 0; memset(head, -1, sizeof(head)); } void add(int u, int v, int w){ edge[cnt] = {u, v, w, head[u]}; head[u] = cnt++; } void getmap(int sum){ for(int i = 1; i <= 24; ++i){ add(i - 1, i, 0); add(i, i - 1, -work[i]); if(i >= 8) add(i - 8, i, need[i]); else add(16 + i, i, need[i] - sum); } add(0, 24, sum); } #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; const int N=100,INF=0x3f3f3f3f; struct node{ int u,v,w,nxt; }e[200010]; int n; int dis[N],head[N],num[N],R[N],tot[N],cnt;//num[]表示第i小時應聘的人, R[]表示第i小時需要的人數 bool vis[N]; inline void init(){ cnt=0; memset(head,-1,sizeof(head)); } inline void add(int u,int v,int w){ e[++cnt].u=u; e[cnt].v=v; e[cnt].w=w; e[cnt].nxt=head[u]; head[u]=cnt; } inline void getsum(int sum){ for(int i=1;i<=24;i++){ add(i-1,i,0); add(i,i-1,-num[i]); if(i>=8) add(i-8,i,R[i]); else add(16+i,i,R[i]-sum); } add(0,24,sum); } inline bool spfa(int sum){ for(int i=0;i<=24;i++){ dis[i]=-INF; vis[i]=0; tot[i]=0; } dis[0]=0; vis[0]=1; tot[0]=1; queue<int>q; q.push(0); while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=e[i].nxt){ int v=e[i].v; int w=e[i].w; if(dis[v]<dis[u]+w){ dis[v]=dis[u]+w; if(!vis[v]){ vis[v]=1; tot[v]++; if(tot[v]>24) return 0; q.push(v); } } } } return dis[24]==sum; } int main(){ int T; scanf("%d",&T); int flag; while(T--){ flag=0; memset(R,0,sizeof(R)); memset(num,0,sizeof(num)); for(int i=1;i<=24;i++) scanf("%d",&R[i]); scanf("%d",&n); for(int i=1,x;i<=n;i++){ scanf("%d",&x); num[x+1]++; } for(int i=0;i<=n;i++){ init(); getsum(i); if(spfa(i)){ flag=1; printf("%d\n",i); break; } } if(!flag) puts("No Solution"); } return 0; }