1. 程式人生 > >ZOJ 2770 Burn the Linked Camp 差分約束 (轉)

ZOJ 2770 Burn the Linked Camp 差分約束 (轉)

最小 差分約束 ast divide sam ges format gen period

It is well known that, in the period of The Three Empires, Liu Bei, the emperor of the Shu Empire, was defeated by Lu Xun, a general of the Wu Empire. The defeat was due to Liu Bei‘s wrong decision that he divided his large troops into a number of camps, each of which had a group of armies, and located them in a line. This was the so-called "Linked Camps".

Let‘s go back to that time. Lu Xun had sent many scouts to obtain the information about his enemy. From his scouts, he knew that Liu Bei had divided his troops into n camps, all of which located in a line, labeled by 1..n from left to right. The ith camp had a maximum capacity of Ci soldiers. Furthermore, by observing the activities Liu Bei‘s troops had been doing those days, Lu Xun could estimate the least total number of soldiers that were lived in from the ith to the jth camp. Finally, Lu Xun must estimate at least how many soldiers did Liu Bei had, so that he could decide how many troops he should send to burn Liu Bei‘s Linked Camps.

Input:

There are multiple test cases! On the first line of each test case, there are two integers n (0<n<=1,000) and m (0<=m<=10,000). On the second line, there are n integers C1??Cn. Then m lines follow, each line has three integers i, j, k (0<i<=j<=n, 0<=k<2^31), meaning that the total number of soldiers from the ith camp to the jth camp is at least k.

Output:

For each test case, output one integer in a single line: the least number of all soldiers in Liu Bei‘s army from Lu Xun‘s observation. However, Lu Xun‘s estimations given in the input data may be very unprecise. If his estimations cannot be true, output "Bad Estimations" in a single line instead.

Sample Input:

3 2 1000 2000 1000 1 2 1100 2 3 1300 3 1 100 200 300 2 3 600 

Sample Output:

1300 Bad Estimations

題目大意:

大家都知道,三國時期,蜀國劉備被吳國大都督陸遜打敗了。劉備失敗的原因是因為劉備的錯誤決策。他把部隊分成幾十個大營,每個大營駐紮一隊部隊,又用樹木編成柵欄,把大營連成一片,稱為連營。
讓我們回到那個時代。陸遜派了很多密探,獲得了他的敵人-劉備的信息。通過密探,他知道劉備的部隊已經分成幾十個大營,這些大營連成一片(一字排開),這些大營從左到右用1...n編號。第i個大營最多能容納Ci個士兵。而且通過觀察劉備軍隊的動靜,陸遜可以估計到從第i個大營到第j個大營至少有多少士兵。最後,陸遜必須估計出劉備最少有多少士兵,這樣他才知道要派多少士兵去燒劉備的大營。
為陸遜估計出劉備軍隊至少有多少士兵。然而,陸遜的估計可能不是很精確,如果不能很精確地估計出來,輸出"Bad Estimations"

對於樣例數據:

數學模型為:設3個軍營的人數分別為A1, A2, A3,容量為C1, C2, C3,前n個軍營的總人數為Sn,則有:

1. 則根據第i個大營到第j個大營士兵總數至少有k個,得不等式組(1):
S2 – S0 >= 1100 等價於 S0 – S2 <= -1100
S3 – S1 >= 1300 等價於 S1 – S3 <= -1300

2. 又根據實際情況,第i個大營到第j個大營的士兵總數不超過這些兵營容量之和,設d[i]為前i個大營容量總和,得不等式組(2):
S2 – S0 <= d[2] – d[0] = 3000
S3 – S1 <= d[3] – d[1] = 3000

3. 每個兵營實際人數不超過容量,得不等式組(3)
A1 <= 1000 等價於 S1 – S0 <= 1000
A2 <= 2000 等價於 S2 – S1 <= 2000
A3 <= 1000 等價於 S3 – S2 <= 1000

4. 另外由Ai>=0,又得到不等式組(4)
S0 – S1 <= 0
S1 – S2 <= 0
S2 – S3 <= 0
求A1+A2+A3的最小值(即S3 – S0的最小值)

構造好網絡之後,最終要求什麽?
要求S3 – S0的最小值,即要求不等式:
S3 – S0 >= M
中的M,轉化成:
S0 – S3 <= -M
即求S3到S0的最短路徑,長度為-M
求得-M為-1300,即M為1300

  1. #include <stdio.h>
  2. #define INF 9999999
  3. int n,m,dist[1010],c[1010],d[1010],ei;
  4. struct eg
  5. {
  6. int u,v,w;
  7. }edges[23000];
  8. void init()
  9. {
  10. ei=0;
  11. int i;
  12. for(i=0;i<=n;i++)
  13. dist[i]=INF;
  14. d[0]=0;
  15. dist[n]=0;
  16. }
  17. bool bell()
  18. {
  19. int i,k,t;
  20. for(i=0;i<n;i++)
  21. {
  22. for(k=0;k<ei;k++)
  23. {
  24. t=dist[edges[k].u]+edges[k].w;
  25. if(dist[edges[k].u]!=INF&&t<dist[edges[k].v])
  26. dist[edges[k].v]=t;
  27. }
  28. }
  29. for(k=0;k<ei;k++)
  30. {
  31. if(dist[edges[k].u]!=INF&&dist[edges[k].u]+edges[k].w<dist[edges[k].v])
  32. return false;
  33. }
  34. return true;
  35. }
  36. int main()
  37. {
  38. while(scanf("%d%d",&n,&m)!=EOF)
  39. {
  40. init();
  41. int i,u,v,w;
  42. for(i=1;i<=n;i++)
  43. {
  44. scanf("%d",&c[i]);
  45. edges[ei].u=i-1;
  46. edges[ei].v=i;
  47. edges[ei].w=c[i];
  48. ei++;
  49. edges[ei].u=i;
  50. edges[ei].v=i-1;
  51. edges[ei].w=0;
  52. ei++;
  53. d[i]=c[i]+d[i-1];
  54. }
  55. for(i=0;i<m;i++)
  56. {
  57. scanf("%d%d%d",&u,&v,&w);
  58. edges[ei].u=v;
  59. edges[ei].v=u-1;
  60. edges[ei].w=-w;
  61. ei++;
  62. edges[ei].u=u-1;
  63. edges[ei].v=v;
  64. edges[ei].w=d[v]-d[u-1];
  65. ei++;
  66. }
  67. if(!bell())
  68. printf("Bad Estimations\n");
  69. else printf("%d\n",-dist[0]);
  70. }
  71. return 0;
  72. }


ZOJ 2770 Burn the Linked Camp 差分約束 (轉)