1.思路
沒什麼好講的,劉汝佳的書《演算法藝術與資訊學競賽》講得很好,不過對於初次接觸差分約束系統的人來講還是很費解,可以去參考《演算法導論》,裡面有很詳細的約束圖的構建過程。這裡講一下我的個人理解。s[i]為從0至i時刻僱傭的人數,t[i]為i時刻應聘的人數,r[i]為i至(i+1)%24時間段需要的最少人數,得出約束條件:
s[i]-s[i-1]>=0
s[i]-s[i-1]<=t[i] 〈==〉s[i-1]-s[i]>=-t[i]
s[i]-s[-1]>=sum
s[i]-s[j]>=r[i] i>j,i=(j+8)mod24
s[i]-s[j]>=r[i]-sum i
i的範圍應該是1~23,因為-1時刻是沒有定義的,但是這樣的話0時刻的約束s[0]>=0,s[0]<=t[0]就沒有考慮在內,為了引入這兩個約束條件我們設s[-1]=0,則s[0]=s[0]-s[-1]>=0,
s[0]-s[-1]<=t[0],因此可以把i的範圍調整為0~23,這樣可以避免對0時刻的特殊討論!我們可以把-1作為乙個參考點s,,23作為目標點t,我取-1為24,連線參考點至每乙個點一條邊,邊權為0(因為每個點都有可能約束其它點),相當於給每個點賦了乙個基礎值d=0,個人覺得隨便賦值多少都沒關係。導論上也說了,若為約束系統的解,則也是系統的解,只不過我們這裡是要求乙個最少的人數因此取為d=0。最後從小到大列舉sum,求約束系統裡單源s至其它點的最長路(因為這裡取的都是大於關係,舉乙個最簡單的例子a>=b同時對c約束,滿足c>=a,c>=b,顯然這時我們要取c>=a才能使c>=a,c>=b這兩個條件都滿足!相反的若取小於等於關係則是求單源最短路!導論上就是這樣的。)若不存在正圈(通過走正圈約束永遠無法得到全部滿足)則有解退出,否則無解!
有個地方很費解:用spfa()會錯!
2.個人**
#include#includeusing namespace std;
// freopen("data.in","r",stdin);
#include#include#define n 30
#define inf 1000000000//!!
#define wt 8//!!
struct graph
}for(u=0; u<=_v; u++)mat[s][u]=0;
memset(tt,0,sizeof(tt));
}void input()}}
}return true;
}void set()
}bool bellmanford()
int m, a;
cin >> m;
for (int i = 0; i < m; i++)
int sum;
for (sum = 0; sum <= m; sum++) //列舉sum
for (int i = 24; i > 0; i--)
if (s[i-1] + t[i] < s[i])
if (s[24] - sum < s[0])
for (int i = 1; i <= 24; i++)
if (i <= 8 && s[i] < s[i+16] + r[i] - sum)}}
if (count < m && s[24] >= sum)
break;
}if (sum > m)
cout << "no solution" << endl;
else
cout << sum << endl;
}return 0;
}
3.二分列舉的話用下面這段**(直接列舉141ms,黑書上的是47ms,二分列舉16ms)。
void set(int mid,int sign)
}bool sodc(int &cost)
else right=mid;
}else
set(mid,1);
}}
4.拓展及補充
一、若有重邊該怎麼取?
當然這個題目不會,可是如果改3小時的,如下面的案例:13
1 0 011
從小到大列舉答案當ans=1時
g[2][1]有兩個取值0和-1。這時該怎麼取呢?或者這時差分約束已經不適應了?
我構的圖源點s=3,目標點t=2
構出的圖矩陣表示為
-inf 0 0 -inf
0 -inf 0 -inf
-inf 0/-1 -inf -inf
0 0 0 0
最後一行零表示源點到每乙個的距離為0,-inf為不可達,自身與自身的不可達是為了spfa時不加判斷語句v!=u。
二、還有我對從源點s至目標t的邊的理解是dis[t]=ans>0在圖中可能會構成正圈,也就是無解的狀態,但是不加這條邊的話,本來有正圈的(無解)會當成了無正圈(有解)輸出!
POJ 1275 二分 差分約束系統
題意 傳送門 poj 1275 cashier employment 題解不等式問題,考慮轉化為差分約束系統。某個時刻 i ii 的工作人數為前 8 88 個小時內開始工作的人數和,將其轉化為字首和 s ss 的差分。設 num i num i num i 為工作開始時間為時刻 i ii 的人數。s...
poj1275 (二分 差分約束)
題意 在一家超市裡,每個時刻都需要有營業員看管,r i 0 i 24 表示從i時刻開始到i 1時刻需要的營業員的數目,現在有n n 1000 個申請人申請這項工作,並且每個申請者都有乙個起始工作時間 ti,如果第i個申請者被錄用,那麼他會從ti時刻開始連續工作8小時。現在要求選擇一些申請者進行錄用,...
poj1716 差分約束系統
ceoi的題,很經典!對於區間問題,思路很多,但如果條件都是關於不等式的,那麼就自然而然的聯想到差分約束系統。一看到區間,我就會聯想到字首和,而這道題正好用上了。令sum i 為從0 i選取到集合的個數的字首和,則有題目條件可得 對於區間 ai,bi sum bi sum ai 1 2 隱含條件 0...