• <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...
            仔細看題,發現maximum total number will be 20000, 所以超時幾乎是肯定的
            其實,discuss里有人用DFS+Cut通過的,只是自己太菜,還不會減枝

            2. 動態規劃
            2.1 from: 
            http://www.shnenglu.com/AClayton/archive/2007/09/14/32185.html
            聲明數組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背包模型(見:背包九講)
            關鍵是下面的數論知識:
            對于任意一個正整數 n, 它可以表示成:
                  n = 1 + 1<<1 + 1<<2 + ... + 1<<k + res[余數]
            我們可以得到:對于1<=i<=n的任意正整數 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狀態方程:
                  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 閱讀(221) 評論(0)  編輯 收藏 引用 所屬分類: C_動態規劃

            導航

            <2010年7月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統計

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            色综合久久久久| 亚洲AV无码久久精品狠狠爱浪潮| 久久超碰97人人做人人爱| 亚洲国产精品无码久久久蜜芽 | 亚洲人成无码网站久久99热国产 | 精品久久久久成人码免费动漫| 欧美日韩精品久久久久| www.久久热| 老男人久久青草av高清| 国内精品久久久久久野外| 久久精品18| 国产美女久久久| 久久这里只有精品首页| 色综合久久中文色婷婷| 久久婷婷五月综合97色一本一本| 99久久婷婷国产一区二区| 一本久久知道综合久久| 久久人人超碰精品CAOPOREN| 成人综合伊人五月婷久久| 亚洲色婷婷综合久久| 免费精品久久久久久中文字幕| 2021精品国产综合久久| 久久久久亚洲av综合波多野结衣| 99久久精品国产一区二区| 久久精品欧美日韩精品| 国产成年无码久久久免费| 三级片免费观看久久| 久久艹国产| 久久国产成人午夜AV影院| 99久久免费国产精品热| 久久亚洲中文字幕精品有坂深雪| 亚洲伊人久久精品影院| 久久婷婷五月综合97色直播| 久久香蕉国产线看观看猫咪?v| 国产高清美女一级a毛片久久w| 国产AV影片久久久久久| 日本道色综合久久影院| 精品久久久久久无码人妻蜜桃| 久久综合久久综合久久综合| 青青青青久久精品国产h| 久久精品国产72国产精福利|