• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            pku 1180 Batch Scheduling 經(jīng)典斜率優(yōu)化

            題意:
            N個(gè)任務(wù),每個(gè)任務(wù)有兩個(gè)參數(shù),完成需要的時(shí)間t以及因子f,現(xiàn)在將這些任務(wù)分組,加工每個(gè)分組前機(jī)器需要冷卻時(shí)間start,完成一組任務(wù)耗時(shí)為 t + Start + (Tx + Tx+1 + ... + Tx+k),問(wèn)最少耗費(fèi)的時(shí)間。
            解法:
            首先先解決這個(gè)問(wèn)題,在這種分組數(shù)不確定的問(wèn)題中,根據(jù)背包九講中無(wú)限背包的策略,外層循環(huán)只要一層即可完成。
            關(guān)鍵是內(nèi)重循環(huán)還要枚舉本組的起始位置,如果暴力的做就要N2了。
            下面試圖對(duì)初始的DP方程進(jìn)行優(yōu)化
            考慮兩種規(guī)劃方向,第一種規(guī)劃方向是從前到后
            dp[i]=min{dp[k]+(dp[k]+sumt(i)-sumt(k)+start)*(sumf(i)-sumf(k))} 無(wú)比復(fù)雜的一個(gè)式子,推了N小時(shí),在這個(gè)式子上下手似乎非常困難。。。(3個(gè)決策變量)
            但是,如果換種思路,從后向前,將sumt以及sumf重新定義為最后一個(gè)任務(wù)到第i個(gè)任務(wù)的時(shí)間和和參數(shù)和,這樣就簡(jiǎn)單多了。
            dp[i]=min{dp[k]+(sumt(i)-sumt(k)+start)*sumf(i)}
            然后很輕易能發(fā)現(xiàn)這個(gè)滿足斜率優(yōu)化的條件(2個(gè)待定決策變量,sumt(k)和dp(k))。
            關(guān)于斜率優(yōu)化,一般有代數(shù)和幾何兩種方法。先說(shuō)幾何方法
            令g=dp[k]+(sumt(i)-sumt(k)+start)*sumf(i)},y=dp[k],x=sumt[k]
            現(xiàn)在要使g最小
            將式子整理下
            y=sumf(i)*x+f-(start+sumt(i))*sumf(i)
            將這個(gè)看做一個(gè)線性函數(shù),目標(biāo)要使得截距最小
            再觀察一下,斜率sumf(i)恒為正,且是隨著i單調(diào)遞減的,換句話說(shuō),是隨著規(guī)劃的過(guò)程單調(diào)遞增的,而自變量x也是隨著規(guī)劃的過(guò)程單調(diào)遞增的。我們畫(huà)個(gè)圖比劃下

            首先,我們要維護(hù)的是一個(gè)上凹線,因?yàn)榘季€內(nèi)部的點(diǎn)不會(huì)被斜率為正的直線切到。再者,我們發(fā)現(xiàn)最優(yōu)決策就在凹線的左端。我們來(lái)觀察藍(lán)色的線,假設(shè)這個(gè)是第i階段的決策線,灰色凹線與藍(lán)色線切點(diǎn)左側(cè)的綠色部分顯然是可以丟棄的。應(yīng)為在切點(diǎn)處截距達(dá)到最小。并且在以后的決策中(淺藍(lán)色的線),該段同樣不會(huì)有任何作用。根據(jù)以上觀察,我們可以使用棧隊(duì)列(很多人簡(jiǎn)稱為單調(diào)隊(duì)列)的數(shù)據(jù)結(jié)構(gòu)。這個(gè)東西網(wǎng)上介紹的比較多,我就不細(xì)說(shuō)了。
            第二種方法就是代數(shù)法。
            我看網(wǎng)上有一個(gè)牛寫的不錯(cuò),就貼過(guò)來(lái)吧- -

            引自http://hi.baidu.com/wangkun_zhen/blog/item/5e85d0cc4fb887590fb345dd.html     dp[i] = min{dp[j] + (S + sumT[i] - sumT[j]) * sumF[i]        { i < j <= n + 1 }  
                                                                                  邊界條件 dp[n+1] = 0
                                                                                                 sumT[n+1]=sumF[n+1]=0
                     
                    
            可以清楚的看到,此種DP方法的時(shí)間復(fù)雜度是O(n^2)的,那么如何降低復(fù)雜度呢?


            經(jīng)典的優(yōu)化分析:
                    
            我們考慮在計(jì)算dp[i]時(shí),對(duì)于i < j < k來(lái)說(shuō), 如果保證決策k比決策j大的條件是:

                     dp[j] + (S + sumT[i] - sumT[j]) * sumF[i] < dp[k] + (S + sumT[i] - sumT[k]) * sumF[i]


            通過(guò)移項(xiàng)整理,可以化簡(jiǎn)為:

                                    (dp[j] - dp[k]) / (sumT[j] - sumT[k]) < sumF[i]

            這個(gè)類似于斜率的東西又怎么來(lái)優(yōu)化?
            為了證明和更好的說(shuō)明接下來(lái)的優(yōu)化,我們定義這么幾個(gè)變量:
            設(shè):   
                              d[i, x] = dp[x] + (S + sumT[i] - sumT[x]) * sumF[i] ;                 
                              g[j, k] = (dp[j] - dp[k]) / (sumT[j] - sumT[k])

            那么我們可以總結(jié)一下上面推出來(lái)的式子:

            根據(jù)上面有:
                                           i<j<k
            同理可證:             d[i, j] < d[i, k]    <=>   g[j, k] < sumF[i]         決策j比決策k

            進(jìn)而我們發(fā)現(xiàn)這么一個(gè)問(wèn)題,當(dāng)i < j < k < l時(shí),如果有g[j, k] < g[k, l],那么k永遠(yuǎn)都不會(huì)成為計(jì)算dp[i]時(shí)的決策點(diǎn)。

            證明:
            如果g[j, k] < g[k, l],那么我們可以分兩個(gè)方面考慮g[j, k]sumF[i]的關(guān)系:
            (1)
            如果g[k, l] >= sumF[i],那么決策k大于等于決策l,也就說(shuō)決策k不可能是決策點(diǎn)
            (2)
            如果g[j, k] < sumF[i],那么決策k要大于決策j,所以k也不可能是決策點(diǎn)

            根據(jù)上面的結(jié)論和一些特性,我們可以考慮維護(hù)一個(gè)斜率的雙向隊(duì)列來(lái)優(yōu)化整個(gè)DP過(guò)程:

            (1)
            假設(shè)i(馬上要入隊(duì)的元素) <j< k依次是隊(duì)列尾部的元素,那么我們就要考慮g[i, j]是否大于g[j, k],如果g[i, j] < g[j, k],那么可以肯定j一定不會(huì)是決策點(diǎn),所以我們可以從隊(duì)列中將j去掉,然后依次向前推,直到找到一個(gè)隊(duì)列元素少于3個(gè)或者g[i j] >= g[j, k]的點(diǎn)才停止。
            (2)
            假設(shè)a>b(a是頭元素)是依次是隊(duì)列頭部的元素,那么我們知道,如果g[b, a] < sumF[i]的話,那么對(duì)于i來(lái)說(shuō)決策點(diǎn)b肯定優(yōu)于決策點(diǎn)a,又由于sumF[i]是隨著i減少而遞增的(這個(gè)就是為什么倒推的原因),所以當(dāng)g[a, b] < sumF[i]時(shí),就一定有g[a, b] < sumF[i-1],因此當(dāng)前的決策點(diǎn)a不僅僅在考慮dp[i]時(shí)不會(huì)是最佳決策點(diǎn),而且在后面的DP中也一定不會(huì)是最佳決策點(diǎn),所以我們可以把a從隊(duì)列 的頭部刪除,依次往后如此操作,直到隊(duì)列元素小于2或者g[b, a] >= sumF[i]
            (3)
            對(duì)于i的更新,一定是隊(duì)列頭部的決策點(diǎn)最好,所以O(1)即可轉(zhuǎn)移。


            初始化的時(shí)候要注意,必須在n+1的位置處加一個(gè)虛擬的狀態(tài),不能將第一個(gè)狀態(tài)(即i=n的狀態(tài))作為初始狀態(tài),因?yàn)榭赡軐⑺腥蝿?wù)僅分為一段。
            代碼:

             

             1# include <stdio.h>
             2# define N 10005
             3int n,start,st[N],sf[N];
             4int q[N],s=-1,e=0;
             5int dp[N];
             6int cmp(const int a,const int b,const int k)
             7{
             8    if(dp[b]-dp[a]<(long long)k*(st[b]-st[a])) return -1;
             9    else if((long long)dp[b]-dp[a]==(long long)k*(st[b]-st[a])) return 0;
            10    else return 1;
            11}

            12int cmp1(const int y1,const int x1,const int y2,const int x2,const int y3,const int x3)
            13{
            14    if(((long long)y3-y2)*(x2-x1)<((long long)y2-y1)*(x3-x2)) return -1;
            15    else if(((long long)y3-y2)*(x2-x1)==((long long)y2-y1)*(x3-x2)) return 0;
            16    else return 1;
            17}

            18int main()
            19{
            20    int i;
            21    scanf("%d%d",&n,&start);
            22    for(i=0;i<n;i++)
            23        scanf("%d%d",st+i,sf+i);
            24    for(i=n-2;i>=0;i--)
            25    {
            26        st[i]+=st[i+1];
            27        sf[i]+=sf[i+1];
            28    }

            29    q[e]=n;
            30    dp[n]=0;
            31    for(i=n-1;i>=0;i--)
            32    {
            33       while(e>=s+2&&cmp(q[s+1],q[s+2],sf[i])!=1) s++;
            34       dp[i]=dp[q[s+1]]+(start+st[i]-st[q[s+1]])*sf[i];
            35       while(e>=s+2&&cmp1(dp[q[e-1]],st[q[e-1]],dp[q[e]],st[q[e]],dp[i],st[i])!=1) e--;
            36       q[++e]=i;
            37    }

            38    printf("%d\n",dp[0]);
            39    return 0;
            40}

            41

            posted on 2011-01-03 21:52 yzhw 閱讀(634) 評(píng)論(1)  編輯 收藏 引用 所屬分類: DP

            評(píng)論

            # re: pku 1180 Batch Scheduling 經(jīng)典斜率優(yōu)化 2011-04-04 14:27 ningbohezhijun

            博主,此題感覺(jué)很難,自認(rèn)為勉強(qiáng)看懂吧,但是為什么說(shuō)這題很經(jīng)典呢?有什么推廣價(jià)值嗎?  回復(fù)  更多評(píng)論   

            <2010年11月>
            31123456
            78910111213
            14151617181920
            21222324252627
            2829301234
            567891011

            導(dǎo)航

            統(tǒng)計(jì)

            公告

            統(tǒng)計(jì)系統(tǒng)

            留言簿(1)

            隨筆分類(227)

            文章分類(2)

            OJ

            最新隨筆

            搜索

            積分與排名

            最新評(píng)論

            閱讀排行榜

            欧美亚洲国产精品久久| 久久久免费观成人影院| 国产精品免费看久久久| 伊人久久大香线焦综合四虎| 国内精品久久久久久久coent| 婷婷综合久久中文字幕| 99久久婷婷国产综合亚洲| 国产精品成人99久久久久 | 精品久久久久香蕉网| 精品免费久久久久国产一区| 久久精品久久久久观看99水蜜桃| 久久国产乱子精品免费女| 久久人人爽人人爽人人av东京热| 久久亚洲精品视频| 亚洲综合熟女久久久30p| 久久青青草原精品国产不卡| 久久夜色tv网站| jizzjizz国产精品久久| 人妻精品久久无码区| 伊人久久大香线蕉AV色婷婷色| 久久久久国产精品三级网| 国产Av激情久久无码天堂| 国产69精品久久久久9999| 久久综合五月丁香久久激情| 久久国产精品成人片免费| 久久天天躁狠狠躁夜夜躁2014| 青青青伊人色综合久久| 久久精品国产第一区二区三区| 亚洲国产高清精品线久久| 久久国产影院| 久久精品夜色噜噜亚洲A∨| 久久er国产精品免费观看8| 国产精自产拍久久久久久蜜| 国产69精品久久久久99| 国产精自产拍久久久久久蜜| 国产精品伦理久久久久久| 国产99久久久久久免费看| www亚洲欲色成人久久精品| 精品人妻伦九区久久AAA片69| 久久精品国产只有精品66| 久久久久亚洲精品无码网址|