• <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_動態規劃

            導航

            <2011年9月>
            28293031123
            45678910
            11121314151617
            18192021222324
            2526272829301
            2345678

            統計

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲AV无码1区2区久久| 久久久久国色AV免费看图片| 久久天天婷婷五月俺也去| 久久亚洲欧洲国产综合| 久久午夜免费视频| 久久精品aⅴ无码中文字字幕重口| 国产韩国精品一区二区三区久久| 国产福利电影一区二区三区久久老子无码午夜伦不 | 伊人热人久久中文字幕| 欧美久久天天综合香蕉伊| 久久AV高潮AV无码AV| 99久久成人18免费网站| 久久精品国产男包| 久久久青草久久久青草| 久久人人爽人人爽人人片AV东京热 | 国产精品久久久天天影视| 午夜福利91久久福利| 九九久久99综合一区二区| 久久久久久精品免费免费自慰| 99久久精品费精品国产| 日韩av无码久久精品免费| 久久国产香蕉视频| 99久久精品毛片免费播放| 亚洲国产精品无码久久一线 | 亚洲精品乱码久久久久久蜜桃不卡| 国产成人香蕉久久久久| 国产精品免费福利久久| 国产成人无码精品久久久性色| 久久久久久亚洲精品不卡| 2021精品国产综合久久| 久久午夜无码鲁丝片| 久久www免费人成看片| 久久天天躁夜夜躁狠狠| 亚洲人成无码久久电影网站| 久久夜色精品国产亚洲av| 伊人久久综合热线大杳蕉下载| 欧美777精品久久久久网| 精品久久无码中文字幕| 国产午夜久久影院| 久久97精品久久久久久久不卡| 国产精品一区二区久久|