• <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 閱讀(209) 評論(0)  編輯 收藏 引用 所屬分類: C_動態規劃

            導航

            <2010年10月>
            262728293012
            3456789
            10111213141516
            17181920212223
            24252627282930
            31123456

            統計

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            国产免费久久久久久无码| 久久99毛片免费观看不卡| 亚洲国产另类久久久精品小说| 亚洲欧美日韩中文久久| 久久综合九色综合久99| 狠狠色丁香久久婷婷综合_中| 大伊人青草狠狠久久| 久久久精品波多野结衣| 国产精品久久久亚洲| 国内精品伊人久久久久777| 久久国产视频网| 9999国产精品欧美久久久久久| 欧美亚洲国产精品久久| 精品国产乱码久久久久久浪潮| 狠狠色丁香久久综合五月| 九九久久99综合一区二区| 久久夜色精品国产噜噜噜亚洲AV| 污污内射久久一区二区欧美日韩 | 77777亚洲午夜久久多喷| 中文字幕久久精品无码| 久久久久亚洲精品天堂| 久久午夜伦鲁片免费无码| 97久久精品午夜一区二区| av无码久久久久久不卡网站| 久久国产精品久久久| 久久久久综合中文字幕| 久久精品卫校国产小美女| 久久久久亚洲AV片无码下载蜜桃 | 久久久久久av无码免费看大片| 久久久久久精品免费看SSS| 久久久久亚洲AV成人网人人网站| 国产精品久久国产精麻豆99网站| 久久久久亚洲av成人无码电影| 人妻少妇久久中文字幕| 狠狠人妻久久久久久综合蜜桃 | 久久91精品国产91| 久久夜色精品国产亚洲| 国产69精品久久久久APP下载| 久久精品国产69国产精品亚洲| 麻豆国内精品久久久久久| a级毛片无码兔费真人久久|