【NOI2012】美食节
Description
CZ 市為了歡迎全國(guó)各地的同學(xué),特地舉辦了一場(chǎng)盛大的美食節(jié)。
作為一個(gè)喜歡嘗鮮的美食客,小 M 自然不愿意錯(cuò)過這場(chǎng)盛宴。他很快就嘗遍了美食節(jié)所有的美食。然而, 嘗鮮的欲望是難以滿足的。盡管所有的菜品都很可口,廚師做菜的速度也很快,小 M 仍然覺得自己桌上沒有已經(jīng)擺在別人餐桌上的美食是一件無法忍受的事情。于是小 M 開始研究起了做菜順序的問題,即安排一個(gè)做菜的順序使得同學(xué)們的等待時(shí)間最短。
小 M 發(fā)現(xiàn),美食節(jié)共有 n n 種不同的菜品。每次點(diǎn)餐,每個(gè)同學(xué)可以選擇其中的一個(gè)菜品。總共有 mm 個(gè)廚師來制作這些菜品。當(dāng)所有的同學(xué)點(diǎn)餐結(jié)束后,菜品的制作任務(wù)就會(huì)分配給每個(gè)廚師。然后每個(gè)廚師就會(huì)同時(shí)開始做菜。 廚師們會(huì)按照要求的順序進(jìn)行制作,并且每次只能制作一人份。
此外,小 M 還發(fā)現(xiàn)了另一件有意思的事情——雖然這 m m 個(gè)廚師都會(huì)制作全部的 nn 種菜品,但對(duì)于同一菜品,不同廚師的制作時(shí)間未必相同。他將菜品用 1,2,…,n 1 , 2 , … , n 依次編號(hào),廚師用 1,2,…,m 1 , 2 , … , m 依次編號(hào),將第 j j 個(gè)廚師制作第 i 種菜品的時(shí)間記為 Ti,jTi,j 。
小 M 認(rèn)為:每個(gè)同學(xué)的等待時(shí)間為所有廚師開始做菜起,到自己那份菜品完成為止的時(shí)間總長(zhǎng)度。換句話說,如果一個(gè)同學(xué)點(diǎn)的菜是某個(gè)廚師做的第 k k 道菜,則他的等待時(shí)間就是這個(gè)廚師制作前 kk 道菜的時(shí)間之和。 而總等待時(shí)間為所有同學(xué)的等待時(shí)間之和。
現(xiàn)在,小 M 找到了所有同學(xué)的點(diǎn)菜信息——有 ai a i 個(gè)同學(xué)點(diǎn)了第 i i 種菜品(i=1,2,…,ni=1,2,…,n) 。他想知道的是最小的總等待時(shí)間是多少。
Input
輸入文件的第 1 1 行包含兩個(gè)正整數(shù) nn 和 m m ,表示菜品的種數(shù)和廚師的數(shù)量。
第 22 行包含 n n 個(gè)正整數(shù),其中第 ii 個(gè)數(shù)為 ai a i ,表示點(diǎn)第 i i 種菜品的人數(shù)。
接下來有 nn 行,每行包含 m m 個(gè)非負(fù)整數(shù),這 nn 行中的第 i i 行的第 jj 個(gè)數(shù)為 Ti,j T i , j ,
表示第 j? j 個(gè)廚師制作第 i i 種菜品所需的時(shí)間。
輸入文件中每行相鄰的兩個(gè)數(shù)之間均由一個(gè)空格隔開,行末均沒有多余空格。
Output
輸出僅一行包含一個(gè)整數(shù),為總等待時(shí)間的最小值。
Data Constraint
對(duì)于 100% 100% 的數(shù)據(jù), n≤40,m≤100,a≤800,ti,j≤1000 n ≤ 40 , m ≤ 100 , a ≤ 800 , t i , j ≤ 1000 (其中 a=∑ai? a = ∑ a i ,即點(diǎn)菜同學(xué)的總?cè)藬?shù))。
Sample Input
3 2
3 1 1
5 7
3 6
8 9
Sample Output
47
Hint
廚師 1 1 先制作 11 份菜品 2 2 ,再制作 22 份菜品 1 1 。點(diǎn)這 33 道菜的 3 3 個(gè)同學(xué)的等待時(shí)間分別為 3,3+5=8,3+5+5=133,3+5=8,3+5+5=13。
廚師 2 2 先制作 11 份菜品 1 1 ,再制作 11 份菜品 3 3 。點(diǎn)這 22 道菜的 2 2 個(gè)同學(xué)的等待時(shí)間分別為 7,7+9=167,7+9=16。
總等待時(shí)間為 3+8+13+7+16=47 3 + 8 + 13 + 7 + 16 = 47 。
雖然菜品 1 1 和菜品 33 由廚師 1 1 制作更快,如果這些菜品都由廚師 11 制作,總等待時(shí)間反而更長(zhǎng)。如果按上述的做法,將 1 1 份菜品 11 和 1 1 份菜品 33 調(diào)整到廚師 2 2 制作,這樣廚師 22 不會(huì)閑著,總等待時(shí)間更短。
可以證明,沒有更優(yōu)的點(diǎn)餐方案。
Solution
很明顯是一道網(wǎng)絡(luò)流題目,先闡述連邊方法:
對(duì)于每個(gè)廚師,后做的菜不會(huì)影響前面做的菜,所以先從倒數(shù)第一時(shí)刻連邊。
為什么不能一下把所有時(shí)刻的邊連好呢?因?yàn)檫厰?shù)太多啦!(屈指一算大約有 n?(m?∑a[i]+1) n ? ( m ? ∑ a [ i ] + 1 ) 條邊!)
所以思路就是,如果某廚師沒做第 ?i? i 道菜,那他就不可能做第 ?i+1? i + 1 道菜。每做一道菜,就為前一道菜(時(shí)刻)連邊繼續(xù)做流,且費(fèi)用為 Ci?ti,j C i ? t i , j , Ci C i 為倒數(shù)第幾道。
Code
var s,ans,n,m,tot,p,i,j:longint;dt,xx,yy,cont1,cont2,next,g,path:array[0..2000000] of longint;vis:array[0..100005] of boolean;dis:array[0..100005] of longint;a:array[1..100] of longint;t:array[1..100,1..100] of longint; procedure make(x,y,liu,fei:longint); begininc(tot);xx[tot]:=x;yy[tot]:=y;cont1[tot]:=liu;cont2[tot]:=fei;next[tot]:=g[x];g[x]:=tot; end; procedure init; var i,j:longint; beginreadln(n,m);for i:=1 to n do beginread(a[i]);inc(p,a[i]);end;for i:=1 to m do beginmake(0,(i-1)*p+1,1,0);make((i-1)*p+1,0,0,0);end;readln;for i:=1 to n do beginfor j:=1 to m do beginread(t[i,j]);make(p*(j-1)+1,p*m+i,1,t[i,j]);make(p*m+i,p*(j-1)+1,0,-t[i,j]);end;make(p*m+i,p*m+n+1,a[i],0);make(p*m+n+1,p*m+i,0,0);readln;end; end; function bfs:boolean; var l,r,i,j,x,y,mm:longint; begindt[1]:=s;fillchar(dis,sizeof(dis),127);fillchar(vis,sizeof(vis),false);mm:=dis[1];dis[0]:=1;l:=0;r:=1;vis[0]:=true;while l<r do begininc(l);if l=100000 then l:=0;x:=dt[l];i:=g[x];while i<>0 do beginy:=yy[i];if (cont2[i]+dis[x]<dis[y]) and (cont1[i]<>0) then begindis[y]:=dis[x]+cont2[i];path[y]:=i;if not vis[y] then begininc(r);if r=100000 then r:=0;dt[r]:=y;vis[y]:=true;end;end;i:=next[i];end;vis[x]:=false;end;if dis[m*p+n+1]=mm then exit(false) else exit(true); end; procedure fl; var i,x,y,v,qv,ci:longint; beginx:=path[m*p+n+1];v:=maxlongint;while x<>0 do beginif v>cont1[x] then v:=cont1[x];if xx[x]=0 then beginy:=yy[x];qv:=(y-1) div p+1;ci:=y mod p+1;end;x:=path[xx[x]];end;x:=path[m*p+n+1];while x<>0 do begindec(cont1[x],v);inc(cont1[x xor 1],v);ans:=ans+cont2[x]*v;x:=path[xx[x]];end;make(0,(qv-1)*p+ci,1,0);make((qv-1)*p+ci,0,0,0);for i:=1 to n do beginmake((qv-1)*p+ci,m*p+i,1,ci*t[i,qv]);make(m*p+i,(qv-1)*p+ci,0,-ci*t[i,qv]);end; end; begintot:=1;init;while bfs do fl;writeln(ans); end.總結(jié)
以上是生活随笔為你收集整理的【NOI2012】美食节的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10V45-ASEMI超低VF值肖特基1
- 下一篇: SVN Cannot verify lo