• <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>

            A Za, A Za, Fighting...

            堅信:勤能補拙

            PKU 1014 Dividing

            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1014

            思路:
            1. 深度搜索
            看到該題的第一個想法就是DFS,很快就寫出了代碼:
             1 void
             2 dfs(int *values, int index, long cur_value_sum)
             3 {
             4     if(cur_value_sum >= value_half) {
             5         if(cur_value_sum == value_half)
             6             flag = 1;
             7         return;
             8     }
             9     if(index < 1)
            10         return;
            11     int i;
            12     for(i=values[index]; i>=0 && (!flag); i--) {
            13         cur_value_sum += (i*index);
            14         dfs(values, index-1, cur_value_sum);
            15         cur_value_sum -= (i*index);
            16     }
            17 }
            額...結果TLE...
            仔細看題,發(fā)現(xiàn)maximum total number will be 20000, 所以超時幾乎是肯定的
            其實,discuss里有人用DFS+Cut通過的,只是自己太菜,還不會減枝

            2. 動態(tài)規(guī)劃
            2.1 from: 
            http://www.shnenglu.com/AClayton/archive/2007/09/14/32185.html
            聲明數(shù)組can_reach[60005]
            can_reach[i]=1, 表示存在一個人獲得價值為 i ,另一個人獲得價值為value_sum-i的方案
            我們的目標就是要確定can_reach[value_sum>>1]是否等于1
             1 int
             2 dp()
             3 {
             4     int i, j, k, temp, cur_max = 0;
             5     can_reach[0= 1;
             6     for(i=1; i<=VALUE_MAX; i++) {
             7         if(num[i] > 0) {
             8             for(j=cur_max; j>=0; j--) { /* tricky, pay attention */
             9                 if(can_reach[j]) {
            10                     for(k=1; k<=num[i]; k++) {
            11                         temp = i*k+j;
            12                         if(temp == value_half)
            13                             return 1;
            14                         if(temp>value_half) /*  initial: if(temp>value_half || can_reach[temp]) break; */
            15                             break;
            16                         can_reach[temp] = 1;
            17                     }
            18                 }
            19             }
            20         }
            21         cur_max += (i*num[i]);
            22         if(cur_max>value_half)
            23             cur_max = value_half;
            24     }
            25 }
            注意: 上述代碼的第14行,原文中存在減枝,但沒有看懂,所以沒有放進去,還好,該代碼還是AC了

            2.2  from: http://blog.sina.com.cn/s/blog_5c95cb070100cvt8.html
            該問題可以轉化成一個0-1背包模型(見:背包九講)
            關鍵是下面的數(shù)論知識:
            對于任意一個正整數(shù) n, 它可以表示成:
                  n = 1 + 1<<1 + 1<<2 + ... + 1<<k + res[余數(shù)]
            我們可以得到:對于1<=i<=n的任意正整數(shù) i, 它肯定可以表示成: 1, 1<<1, 1<<2, ... 1<<k, res的一個組合
            因此,對于該題,我們可以對輸入做預處理:
             1 len = 0;
             2 memset(value_weight, 0sizeof(value_weight));
             3 for(i=1; i<=VALUE; i++) {
             4     if(num[i] != 0) {
             5          j = 0;
             6          while((1<<(j+1)) <= (num[i]+1)) {
             7                 value_weight[len++= i*(1<<j);
             8                 ++j;
             9          }
            10         if((num[i]+1-(1<<j))>0)
            11         value_weight[len++= i*(num[i]+1-(1<<j));
            12    }
            13 }
            接下來,原問題就轉化成:
            背包容量value_half(value_sum/2),每件物品的cost與value都是value_weight[i],考慮是否存在一種方案,使得總價值等于value_half
            0-1背包的典型DP狀態(tài)方程:
                  f[i][j] = max(f[i-1][j], f[i-1][j-c[i]]+v[i]), f[i][j]表示前i件物品放入容量為j的背包而可以獲得的最大價值
             1 int
             2 knapsack()
             3 {
             4     int i, w, pre, cur;
             5     memset(table, 0sizeof(table));
             6     for(w=value_weight[0]; w<=value_half; w++) {
             7         table[0][w] = value_weight[0];
             8         if(table[0][w] == value_half)
             9             return 1;
            10     }
            11     for(i=1; i<len; i++) {
            12         cur = i%2;
            13         pre = (i+1)%2;
            14         for(w=0; w<=value_half; w++) {
            15             if(w>=value_weight[i])
            16                 table[cur][w] = max(table[pre][w], table[pre][w-value_weight[i]]+value_weight[i]);
            17             else
            18                 table[cur][w] = table[pre][w];
            19             if(table[cur][w] == value_half)
            20                 return 1;
            21         }
            22     }
            23     return 0;
            24 }
            AC [ Memory: 836K, Time: 16MS]

            posted on 2010-06-28 23:30 simplyzhao 閱讀(213) 評論(0)  編輯 收藏 引用 所屬分類: C_動態(tài)規(guī)劃

            導航

            <2011年7月>
            262728293012
            3456789
            10111213141516
            17181920212223
            24252627282930
            31123456

            統(tǒng)計

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            色婷婷久久综合中文久久一本| 久久久久人妻精品一区 | 亚洲人成无码网站久久99热国产| 国产精品成人精品久久久| 久久国产一片免费观看| 99久久香蕉国产线看观香| 少妇久久久久久久久久| 色成年激情久久综合| 人妻无码αv中文字幕久久琪琪布| 久久久噜噜噜www成人网| 三级片免费观看久久| 婷婷久久久亚洲欧洲日产国码AV | 亚洲国产精品久久久久网站| 欧美亚洲日本久久精品| 久久亚洲精品成人AV| 久久午夜综合久久| 韩国免费A级毛片久久| 久久中文字幕精品| 久久精品亚洲精品国产欧美| 国产成人精品久久免费动漫| 久久精品一区二区三区AV| 久久一区二区三区99| 2020最新久久久视精品爱| 久久久久久午夜成人影院| 一本色道久久综合| 亚洲午夜无码AV毛片久久| 久久久久九九精品影院| 久久亚洲国产精品一区二区| 国产麻豆精品久久一二三| 亚洲乱码精品久久久久..| 久久精品国产清自在天天线| 亚洲乱码日产精品a级毛片久久| 国产精品VIDEOSSEX久久发布| 欧美亚洲另类久久综合| 久久精品国产亚洲网站| 青青草国产精品久久| 国产成人无码精品久久久久免费| 久久久久久久99精品免费观看| 久久精品国产网红主播| 国产精品青草久久久久婷婷| 久久精品国产影库免费看|