日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

hdu1529 差分约束(好题)

發布時間:2025/6/17 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu1529 差分约束(好题) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ? 超市在每個時間都有需要的人數(24小時)比如 1 0 0 0 0 。。。。也就是說在第0個小時的時候要用一個人,其他的時間都不用人,在給你一些人工作的起始時間,如果雇傭了這個人,那么這個人就會從自己的其實時間工作8個小時后離開,給你需求和可雇傭的員工,問你滿足需求超時最少雇傭多少人。

思路:
? ? ? 經典的差分約束,之前嘗試過很多次都沒AC,今天終于AC了,現在我們就來找各種隱含條件。

設:
num[i] 表示第i個小時開始的有多少個人。
r[i] 表示第i個小時最少雇傭多少人。
s[i] 表示1。。。i小時開始工作的有多少人。 (我們以S為核心建圖)

限制條件:
第i個小時雇傭并開始工作的人數 >= 0?
則 s[i] - s[i-1] >= 0
第i個小時雇傭并開始工作的人數 <= num[i]?
則 s[i] - s[i-1] <= num[i] 轉化成 s[i-1] - s[i] >= -num[i]
第i個小時雇傭的人數 >= r[i]
則 s[i] - s[i-8] >= r[i] ? ? ? ? ? ? ? (i >= 8 && i <= 24)
? ?s[24] + s[i] - s[i + 16] >= r[i] ? ?(i <= 7)

觀察最后一個不等式,出現了三個變量,不符合差分約束形式,所以我們就直接二分枚舉
s[24]的值,也就是二分枚舉雇傭人數的值,這樣就把最后一個轉換成
s[i] - s[i + 16] >= r[i] - mid
最后別忘了還有一個限制條件就是s[24] - s[0] = mid,=怎么建邊呢?我們可以這樣
s[24] - s[0] >= mid并且 s[24] - s[0] <= mid
第二個轉換成 s[0] - s[24] >= -mid;

這樣就可以二分下去了。。。


#include<stdio.h> #include<string.h> #include<queue>#define N_node 30 #define N_edge 10000 #define INF 1000000000 using namespace std;typedef struct {int to ,cost ,next; }STAR;STAR E[N_edge]; int list[N_node] ,tot; int s_x[N_node]; int r[30] ,num[1100];void add(int a ,int b ,int c) {E[++tot].to = b;E[tot].cost = c;E[tot].next = list[a];list[a] = tot; }bool Spfa(int s ,int n) {for(int i = 0 ;i <= n ;i ++)s_x[i] = -INF;int mark[N_node] = {0};int in[N_node] = {0};s_x[s] = 0;mark[s] = in[s] = 1;queue<int>q;q.push(s);while(!q.empty()){int xin ,tou;tou = q.front();q.pop();mark[tou] = 0;for(int k = list[tou] ;k ;k = E[k].next){xin = E[k].to;if(s_x[xin] < s_x[tou] + E[k].cost){s_x[xin] = s_x[tou] + E[k].cost;if(!mark[xin]){mark[xin] = 1;if(++in[xin] > n) return 0;q.push(xin);}}}}return 1; }bool ok(int mid) {memset(list ,0 ,sizeof(list));tot = 1;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(i + 16 ,i ,r[i] - mid);}add(0 ,24 ,mid);add(24 ,0 ,-mid);return Spfa(0 ,24); }int main () {int t ,i ,a ,n;scanf("%d" ,&t);while(t--){for(i = 1 ;i <= 24 ;i ++)scanf("%d" ,&r[i]);scanf("%d" ,&n);memset(num ,0 ,sizeof(num));for(i = 1 ;i <= n ;i ++){scanf("%d" ,&a);num[a+1] ++;}int low ,mid ,up;low = 0 ,up = n;int ans = -1;while(low <= up){mid = (low + up) >> 1;if(ok(mid)){ans = mid;up = mid - 1;}else low = mid + 1;}if(ans == -1) puts("No Solution");else printf("%d\n" ,ans);}return 0; }


總結

以上是生活随笔為你收集整理的hdu1529 差分约束(好题)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。