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

            堅信:勤能補拙

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

            思路:
            深度優先搜索,找出所有可能的劃分,并適當減枝
            這里搜索的對象是什么?
            我的第一個想法受到了前幾天完成PKU 1950的啟發,對于從高到低的每一位,有兩種可能:
            a. 作為解的一部分,加入總和
            b. 不加入總和,而是作為向下繼續搜索時的高位
            dfs(depth, cur_sum, pre)
            depth: 搜索深度
            cur_sum: 當前總和
            pre: 保留位
            經過一段時間的調試,一次AC了
            存在的問題是:  對于每一種可能的解都會重復記錄兩次,例如:
            輸入 376  144139
            輸出 283  144  139
            dfs(6, 283, 0)與dfs(6, 144, 139)都可以得到該解

            之后,查看了網上的代碼,原來不用想的這么復雜
            對于第k位,我們搜索從其開始的所有可能,然后遞歸,例如:
            對于將被“粉碎"的12346,對于第一位'1',可能的劃分有1, 12, 123, 1234, 12346

            代碼(方法一):
             1 #define MAX_LEN 7
             2 int target, num;
             3 int digits_count, digits[MAX_LEN];
             4 int sum_count, sum, parts_count, parts[MAX_LEN];
             5 int ans_count, ans[MAX_LEN];
             6 
             7 void
             8 init()
             9 {
            10     int i, temp, rem;
            11     memset(digits, -1sizeof(digits));
            12     memset(parts, -1sizeof(parts));
            13     digits_count = sum_count = parts_count = 0;
            14     sum = -1;
            15     rem = num;
            16     do {
            17         digits[digits_count++= rem % 10;
            18         rem /= 10;
            19     } while(rem!=0);
            20     for(i=0; i<digits_count/2; i++) {
            21         temp = digits[i];
            22         digits[i] = digits[digits_count-i-1];
            23         digits[digits_count-i-1= temp;
            24     }
            25 }
            26 
            27 void
            28 dfs(depth, cur_sum, pre)
            29 {
            30     if(cur_sum+pre>target) /* pruning */
            31         return;
            32     //printf("dfs(%d, %d, %d)\n", depth, cur_sum, pre);
            33     if(depth == digits_count) {
            34         if(pre != 0) {
            35             parts[parts_count++= pre;
            36             cur_sum += pre;
            37         }
            38         if(cur_sum == sum)
            39             ++sum_count;
            40         if(cur_sum > sum) {
            41             sum = cur_sum;
            42             sum_count = 1;
            43             ans_count = parts_count;
            44             memcpy(ans, parts, sizeof(int)*ans_count);
            45         }
            46         if(pre != 0)
            47             parts[parts_count--= -1;
            48         return;
            49     }
            50     /* branch 1 */
            51     parts[parts_count++= digits[depth] + pre * 10;
            52     dfs(depth+1, cur_sum+parts[parts_count-1], 0);
            53     parts[parts_count--= -1;
            54     /* branch 2 */
            55     dfs(depth+1, cur_sum, pre*10+digits[depth]);
            56 }

            代碼(方法二):
             1 #define MAX_LEN 7
             2 int target, len;
             3 char num[MAX_LEN];
             4 int sum_count, sum, parts_count, parts[MAX_LEN];
             5 int ans_count, ans[MAX_LEN];
             6 
             7 void
             8 dfs(int depth, int cur_sum)
             9 {
            10     int i, value = 0;
            11     if(cur_sum > target) /* pruning */
            12         return;
            13     if(depth == len) {
            14         if(cur_sum == sum)
            15             ++sum_count;
            16         if(cur_sum > sum) {
            17             sum = cur_sum;
            18             sum_count = 1;
            19             ans_count = parts_count;
            20             memcpy(ans, parts, sizeof(int)*ans_count);
            21         }
            22         return;
            23     }
            24     for(i=depth; i<len; i++) {
            25         value *= 10;
            26         value += (num[i]-'0');
            27         parts[parts_count++= value;
            28         dfs(i+1, cur_sum+value);
            29         parts[parts_count--= -1;
            30     }
            31 }

            posted @ 2010-07-27 17:51 simplyzhao 閱讀(173) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1129

            思路:
            好題,典型的圖著色問題
            首先,對于鄰接關系,可以用二維數組來表示
            具有鄰接關系的節點不能使用同一種顏色,求所需顏色的最小值
            深度優先搜索,當目前使用顏色個數已經超過當前最優解時進行減枝

            代碼:
             1 #define MAX_NUM 29
             2 #define INF 100000
             3 int graph[MAX_NUM][MAX_NUM];
             4 int color[MAX_NUM];
             5 int num, ans;
             6 
             7 void
             8 init()
             9 {
            10     int i, j, len;
            11     char conn[MAX_NUM];
            12     memset(graph, 0sizeof(graph));
            13     memset(color, -1sizeof(color));
            14     ans = INF;
            15     for(i=0; i<num; i++) {
            16         scanf("%s", conn);
            17         len = strlen(conn);
            18         for(j=2; j<len; j++)
            19             graph[i][conn[j]-'A'= 1;
            20     }
            21 }
            22 
            23 int
            24 is_valid(int depth, int cindex)
            25 {
            26     int i;
            27     for(i=0; i<depth; i++)
            28         if(graph[depth][i] && color[i]==cindex)
            29             return 0;
            30     return 1;
            31 }
            32 
            33 void 
            34 dfs(int depth, int used_colors)
            35 {
            36     int i;
            37     if(used_colors >= ans) /* pruning */
            38         return;
            39     if(depth == num) {
            40         ans = used_colors<ans ? used_colors : ans;
            41         return;
            42     }
            43     for(i=1; i<=used_colors; i++) {
            44         if(is_valid(depth, i)) {
            45             color[depth] = i;
            46             dfs(depth+1, used_colors);
            47             color[depth] = -1;
            48         }
            49     }
            50     color[depth] = used_colors+1;
            51     dfs(depth+1, used_colors+1);
            52     color[depth] = -1;
            53 }


            posted @ 2010-07-26 20:47 simplyzhao 閱讀(215) | 評論 (0)編輯 收藏
            問題:
             1 #define ENDALL "ENDOFINPUT"
             2 #define ENDEACH "END"
             3 #define MAX_LEN 250
             4 const char cipher[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
             5 const char plain[] =  "VWXYZABCDEFGHIJKLMNOPQRSTU";
             6 char msg[MAX_LEN];
             7 
             8 void
             9 translate(char *msg)
            10 {
            11     int i, len=strlen(msg);
            12     for(i=0; i<len; i++)
            13         if(msg[i]>='A' && msg[i]<='Z')
            14             msg[i] = plain[msg[i]-'A'];
            15     printf("%s ", msg);
            16 }
            17 
            18 int
            19 main(int argc, char **argv)
            20 {
            21     char temp[15];
            22     while(scanf("%s", temp)!=EOF) {
            23         if(strcmp(temp, ENDALL)==0)
            24             break;
            25         while(scanf("%s", msg) && strcmp(msg, ENDEACH)!=0)
            26             translate(msg);
            27         printf("\n");
            28     }
            29     return 0;
            30 }

            "gets version"
             1 #define ENDALL "ENDOFINPUT"
             2 #define MAX_LEN 250
             3 const char cipher[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
             4 const char plain[] =  "VWXYZABCDEFGHIJKLMNOPQRSTU";
             5 char msg[MAX_LEN];
             6 
             7 void
             8 translate(char *msg)
             9 {
            10     int i, len=strlen(msg);
            11     for(i=0; i<len; i++)
            12         if(msg[i]>='A' && msg[i]<='Z')
            13             msg[i] = plain[msg[i]-'A'];
            14     printf("%s\n", msg);
            15 }
            16 
            17 int
            18 main(int argc, char **argv)
            19 {
            20     char temp[15];
            21     while(gets(temp)!=EOF) {
            22         if(strcmp(temp, ENDALL)==0)
            23             break;
            24         gets(msg);
            25         translate(msg);
            26         gets(temp);
            27     }
            28     return 0;
            29 }
            posted @ 2010-07-26 17:30 simplyzhao 閱讀(129) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1426

            思路:
            典型的BFS,每次擴展都在末尾加上0或者1,例如從1開始,1->10、1->11,10->100,10->101...
            根據這點,就可以寫出AC的代碼,不過這樣所需內存會比較高昂,因為保存的每個狀態都是long long,并且狀態數目非常多

            參考網上代碼,發現這里可以應用鴿巢原理
            對于m取模,其結果只有0, 1, ..., m-1這幾種可能,因此很可能出現重復
            另外,如果擴展前remainder是k, 那么擴展之后的remainder可以通過((k*10)+0/1)%num計算得到

            如何記錄結果也是比較tricky的,這里在每個狀態中只保留一位以及指向擴展前狀態的指針,輸出的時候只要遞歸即可

            代碼:
             1 struct EACH {
             2     int remainder;
             3     int digit;
             4     struct EACH *pre;
             5 }queue[QUEUE_MAX];
             6 int hash[REMAINDER_MAX];
             7 int head, tail;
             8 int num;
             9 
            10 void
            11 output(struct EACH *end)
            12 {
            13     if(end==NULL)
            14         return;
            15     output(end->pre);
            16     printf("%d", end->digit);
            17 }
            18 
            19 void
            20 bfs()
            21 {
            22     int cur_rem, next_rem;
            23     queue[tail].remainder = 1%num;
            24     queue[tail].digit = 1;
            25     queue[tail].pre = NULL;
            26     hash[queue[tail].remainder] = 1;
            27     while(head <= tail) {
            28         ++head;
            29         cur_rem = queue[head].remainder;
            30         if(cur_rem == 0) {
            31             output(queue+head);
            32             printf("\n");
            33             return;
            34         }
            35         next_rem = (cur_rem*10+0)%num;
            36         if(!hash[next_rem]) {
            37             ++tail;
            38             queue[tail].remainder = next_rem;
            39             queue[tail].digit = 0;
            40             queue[tail].pre = queue+head;
            41             hash[next_rem] = 1;
            42         }
            43         next_rem = (cur_rem*10+1)%num;
            44         if(!hash[next_rem]) {
            45             ++tail;
            46             queue[tail].remainder = next_rem;
            47             queue[tail].digit = 1;
            48             queue[tail].pre = queue+head;
            49             hash[next_rem] = 1;
            50         }
            51     }
            52 }


            posted @ 2010-07-26 15:46 simplyzhao 閱讀(338) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1321

            思路:
            深度優先搜索
            有點類似于八皇后問題,不過要注意這里k<=n,也就是說: 某些行是可以不放置棋子的

            不過,該題還可以利用位運算進行優化...

            代碼:
             1 char chessboard[MAX_LEN][MAX_LEN];
             2 int record[MAX_LEN];
             3 int n, k;
             4 int total;
             5 
             6 int
             7 is_valid(int i, int depth)
             8 {
             9     int j;
            10     for(j=0; j<depth; j++)
            11         if(record[j] == i)
            12             return 0;
            13     return 1;
            14 }
            15 
            16 void
            17 dfs(int depth, int cur)
            18 {
            19     int i, j;
            20     if(depth == n) {
            21         if(cur == k)
            22             ++total;
            23         return;
            24     }
            25     if(cur+(n-depth) < k) /* pruning */
            26         return;
            27     for(i=0; i<n; i++) {
            28         if(chessboard[depth][i]=='#' && is_valid(i, depth)) {
            29             record[depth] = i;
            30             dfs(depth+1, cur+1);
            31             record[depth] = -1;
            32         }
            33     }
            34     dfs(depth+1, cur);
            35 }

            posted @ 2010-07-26 13:30 simplyzhao 閱讀(146) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1629

            思路:
            這題如果想通了,就是一水題呵呵,不亞于PKU 1000的'A+B Problem'
            該題要求輸出在填滿words之后grid中剩余的字符,并且告訴我們一定存在解
            最簡單的辦法就是對A-Z的字符進行計數,然后輸出

            現在,我們將題目的要求改變一下,找出所有可能的填滿方案(更具挑戰性)
            這可以通過DFS來解決,代碼如下:
            通過調用solve(0)即可獲得所有的方案
            這里,set(x, y, index, ct)是找出對于words[index]的所有可能填充

             1 void
             2 set(int x, int y, int index, int ct)
             3 {
             4     int i, tx, ty;
             5     visited[x][y] = index+1;
             6     if(ct+1 == words_len[index]) {
             7         solve(index+1);
             8         visited[x][y] = 0;
             9         return;
            10     }
            11     for(i=0; i<4; i++) {
            12         tx = x + dx[i];
            13         ty = y + dy[i];
            14         if(is_valid(tx, ty) && !visited[tx][ty] && grid[tx][ty]==words[index][ct+1])
            15             set(tx, ty, index, ct+1);
            16     }
            17     visited[x][y] = 0;
            18 }
            19 
            20 void
            21 solve(int index)
            22 {
            23     int i, j;
            24     if(index == p) {
            25         for(i=0; i<n; i++) {
            26             for(j=0; j<m; j++) {
            27                 printf("%d\t", visited[i][j]);
            28             }
            29             printf("\n");
            30         }
            31         return;
            32     }
            33     char c = words[index][0];
            34     for(i=0; i<n; i++) {
            35         for(j=0; j<m; j++) {
            36             if(grid[i][j]==&& !visited[i][j])
            37                 set(i, j, index, 0);
            38         }
            39     }
            40 }

            posted @ 2010-07-26 10:15 simplyzhao 閱讀(110) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=3278

            思路:
            簡單的BFS,一次AC
            使用一個數組visited[MAX_NUM]來判重

            代碼:
             1 #define ADD(temp, cur) ++tail; \
             2             queue[tail].num = temp; \
             3             queue[tail].moves = cur+1; \
             4             visited[temp] = 1;
             5 
             6 int
             7 bfs()
             8 {
             9     int cur_num, cur_moves, temp;
            10     queue[tail].num = n;
            11     queue[tail].moves = 0;
            12     visited[queue[tail].num] = 1;
            13     while(head <= tail) {
            14         ++head;
            15         cur_num = queue[head].num;
            16         cur_moves = queue[head].moves;
            17         if(cur_num == k)
            18             return cur_moves;
            19         temp = cur_num - 1;
            20         if(temp>=0 && temp<MAX_NUM && !visited[temp]) {
            21             ADD(temp, cur_moves);
            22         }
            23         temp = cur_num + 1;
            24         if(temp>=0 && temp<MAX_NUM && !visited[temp]) {
            25             ADD(temp, cur_moves);
            26         }
            27         temp = cur_num<<1;
            28         if(temp>=0 && temp<MAX_NUM && !visited[temp]) {
            29             ADD(temp, cur_moves);
            30         }
            31     }
            32 }
            posted @ 2010-07-25 21:06 simplyzhao 閱讀(261) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=3256

            思路:
            該題是一道簡單的DFS,結果卻歷經了很多次RE,甚至還TLE,艾...
            首先,對于paths可以用二維數組paths[MAX_N][MAX_N]來表示,雖然是很自然的事情,不過還是體現了選擇合適的數據結構對于解題的幫助
            然后,對于每個起點(pasture in which each cow is grazing from beginning)依次深度優先搜索,并計數
            所有的搜索結束之后,清點計數,若某個pasture的計數等于cows的個數,那么就是符合條件的pasture

            需要注意的一點是如何避免路徑中的環路,這里使用一維數組visited來標記經過的pastures

            代碼:
             1 void
             2 init()
             3 {
             4     int i, j, p;
             5     memset(paths, 0sizeof(paths));
             6     memset(starts, 0sizeof(starts));
             7     memset(counts, 0sizeof(counts));
             8     scanf("%d %d %d"&k, &n, &m);
             9     for(i=1; i<=k; i++)
            10         scanf("%d", starts+i);
            11     for(i=1; i<=m; i++) {
            12         scanf("%d %d"&j, &p);
            13         paths[j][p] = 1;
            14     }
            15 }
            16 
            17 void
            18 solve(int index)
            19 {
            20     int i;
            21     visited[index] = 1;
            22     ++counts[index];
            23     for(i=1; i<=n; i++)
            24         if(paths[index][i] && !visited[i]) {
            25             solve(i);
            26         }
            27 }
            28 
            29 void
            30 output()
            31 {
            32     int i, total=0;
            33     for(i=1; i<=n; i++)
            34         if(counts[i] == k)
            35             ++total;
            36     printf("%d\n", total);
            37 }


            posted @ 2010-07-25 14:19 simplyzhao 閱讀(147) | 評論 (0)編輯 收藏
            問題:
            depth: 搜索深度,即運算符的個數
            cur: 目前表達式的值
            pre: 前一個運算數

            代碼:

            1 #define MAX_N 16
            2 #define MAX_SOLVE 20
            3 int total;
            4 int n;
            5 const int arr[] = { 23456789101112131415 };
            6 const char op[] = {'+''-''.'};
            7 char oparr[MAX_N];

             1 void
             2 solve(int depth, int cur, int pre)
             3 {
             4     if(depth+1 == n) {
             5         cur += pre;
             6         if(cur == 0) {
             7             ++total;
             8             if(total <= MAX_SOLVE)
             9                 output();
            10         }
            11         return;
            12     }
            13     oparr[depth] = op[0];
            14     solve(depth+1, cur+pre, arr[depth]);
            15     oparr[depth] = op[1];
            16     solve(depth+1, cur+pre, -arr[depth]);
            17     oparr[depth] = op[2];
            18     if(arr[depth]>=10)
            19         pre = pre*100 + pre/abs(pre)*arr[depth];
            20     else
            21         pre = pre*10 + pre/abs(pre)*arr[depth];
            22     solve(depth+1, cur, pre);
            23 }
            posted @ 2010-07-25 10:06 simplyzhao 閱讀(156) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1691

            思路:
            首先要解決的問題是如何合理地表示整個Board?
            這題還是在青島洲際無聊的時候用手機看到的,當時想到用一顆樹的父子節點來表示各個矩形之間的上下關系
            其實,這是一個有向圖,而表示的方法則可以很簡單地使用二維數組(因為矩形的個數比較少)進行標記即可
            另一個巧妙之處是記錄每個節點的入度,當入度為零時表示可以Painting
            在用有向圖進行表示之后,剩下的就是搜索了(太菜,參考人家的)

            代碼:
             1 int
             2 solve(int last_color, int count)
             3 {
             4     int i, j, rt;
             5     int ans = 1000000;
             6     for(i=0; i<n; i++) {
             7         if(!visited[i] && degree[i]==0) {
             8             visited[i] = 1;
             9             if(recs[i].color != last_color)
            10                 ++count;
            11             for(j=0; j<n; j++)
            12                 if(graph[i][j])
            13                     --degree[j];
            14             rt = solve(recs[i].color, count);
            15             ans = rt<ans ? rt : ans;
            16             visited[i] = 0;
            17             if(recs[i].color != last_color)
            18                 --count;
            19             for(j=0; j<n; j++)
            20                 if(graph[i][j])
            21                     ++degree[j];
            22         }
            23     }
            24     if(ans == 1000000)
            25         ans = count;
            26     return ans;
            27 }

             1 void
             2 build_graph()
             3 {
             4     int i, j;
             5     for(i=0; i<n; i++
             6         for(j=0; j<n; j++
             7             if(i!=&& is_immdt_above(recs+i, recs+j)) {
             8                 graph[i][j] = 1;
             9                 ++degree[j];
            10             }
            11 }

            1 /* if rec1 is immediate above rec2, return 1 */
            2 int
            3 is_immdt_above(struct Rec *rec1, struct Rec *rec2)
            4 {
            5     if(rec1->lwrgt_x==rec2->uplft_x && !(rec1->lwrgt_y<=rec2->uplft_y || rec1->uplft_y>=rec2->lwrgt_y))
            6         return 1;
            7     return 0;
            8 }
            posted @ 2010-07-24 09:33 simplyzhao 閱讀(178) | 評論 (0)編輯 收藏
            僅列出標題
            共21頁: First 13 14 15 16 17 18 19 20 21 

            導航

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統計

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            国产成人精品三上悠亚久久 | 色8久久人人97超碰香蕉987| 中文字幕精品无码久久久久久3D日动漫| 精品久久久久久国产三级| 狠狠色综合久久久久尤物| 亚洲欧美日韩久久精品| 色欲综合久久躁天天躁蜜桃| 97久久超碰国产精品2021| 久久精品二区| 无码伊人66久久大杳蕉网站谷歌| 国产国产成人精品久久| 久久亚洲国产成人影院网站| 久久无码AV中文出轨人妻| 国产精品久久午夜夜伦鲁鲁| 国产成人久久久精品二区三区| 伊人久久成人成综合网222| 久久天天躁狠狠躁夜夜avapp| 大蕉久久伊人中文字幕| 狠狠色丁香久久婷婷综合蜜芽五月| 9久久9久久精品| 伊人久久大香线蕉综合5g| 久久久久夜夜夜精品国产| 亚洲精品美女久久久久99| 国产AⅤ精品一区二区三区久久| 久久天天躁夜夜躁狠狠| 国产一区二区精品久久凹凸| 久久久久免费精品国产| 久久久久久A亚洲欧洲AV冫 | 久久精品日日躁夜夜躁欧美| 99精品久久精品一区二区| 久久久久久久波多野结衣高潮| 国内精品欧美久久精品| 99久久99这里只有免费费精品| 久久人人爽人人精品视频| 久久99国产精品久久99果冻传媒| 色妞色综合久久夜夜| 久久高潮一级毛片免费| 国产精品久久影院| 亚洲精品无码成人片久久| 久久久久久久女国产乱让韩| 亚洲国产成人精品久久久国产成人一区二区三区综 |