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

            思路:
            原本以為是類似于PKU 1936的簡單題,結果Sample測試不過,發現對于像cat, tree這樣包含相同字母(這里是t)的例子需要回溯,于是DFS,這樣結果雖然正確了,但是卻TLE...
            準確的做法是動態規劃,艾,今天三題沒有一個是自己想出來的...悲劇...
            詳細的狀態轉化方程見代碼注釋

            代碼:
             1 #include<stdio.h>
             2 #include<stdlib.h>
             3 #include<string.h>
             4 #define MAX_LEN 201
             5 char first[MAX_LEN+1], second[MAX_LEN+1];
             6 char final[MAX_LEN*2];
             7 int flen, slen, tlen;
             8 int table[MAX_LEN][MAX_LEN];
             9 
            10 /* 
            11  * f[i][j] represent whether final[1..i+j] could be formed from first[1..i] and second[1..j]
            12  * f[i][j] is true if:
            13  *         a. final[i+j]==first[i] && f[i-1][j] is true, or
            14  *         b. final[i+j]==second[j] && f[i][j-1] is true
            15  */
            16 int 
            17 dp()
            18 {
            19     int i, j, mark;
            20     mark = 1;
            21     for(i=1; i<=flen; i++) {
            22         if(first[i]==final[i] && mark)
            23             table[i][0= 1;
            24         else {
            25             table[i][0= 0;
            26             mark = 0;
            27         }
            28     }
            29     mark = 1;
            30     for(j=1; j<=slen; j++) {
            31         if(second[j]==final[j] && mark)
            32             table[0][j] = 1;
            33         else {
            34             table[0][j] = 0;
            35             mark = 0;
            36         }
            37     }
            38     for(i=1; i<=flen; i++) {
            39         for(j=1; j<=slen; j++) {
            40             if((final[i+j]==first[i]&&table[i-1][j]) || (final[i+j]==second[j]&&table[i][j-1]))
            41                 table[i][j] = 1;
            42             else
            43                 table[i][j] = 0;
            44         }
            45     }
            46     return table[flen][slen];
            47 }
            48 
            49 int
            50 main(int argc, char **argv)
            51 {
            52     int tests, cnt=0;
            53     scanf("%d"&tests);
            54     while(tests--) {
            55         scanf("%s %s %s", first+1, second+1, final+1);
            56         flen = strlen(first+1);
            57         slen = strlen(second+1);
            58         tlen = strlen(final+1);
            59         printf("Data set %d: %s\n"++cnt, dp()?"yes":"no");
            60     }
            61 }
            posted @ 2010-08-13 22:33 simplyzhao 閱讀(204) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1080

            思路:
            想法與最長公共子序列類似
            用f[i][j]表示str_a[1..i]與str_b[1..j]的相似度,而所求即f[len_a][len_b],需要注意初始化部分的代碼
            狀態轉移方程見代碼注釋

            代碼:
             1 #include<stdio.h>
             2 #include<stdlib.h>
             3 #include<string.h>
             4 #define MAX_LEN 101
             5 #define INF 'I'
             6 #define Score(ch_a, ch_b) (score[map[ch_a-'A']][map[ch_b-'A']])
             7 int len_a, len_b;
             8 char str_a[MAX_LEN+1], str_b[MAX_LEN+1];
             9 int table[MAX_LEN][MAX_LEN];
            10 const int score[][5= {{5,-1,-2,-1,-3}, {-1,5,-3,-2,-4}, {-2,-3,5,-2,-2}, {-1,-2,-2,5,-1}, {-3,-4,-2,-1,-65535}};
            11                               /* A    C          G    I                               T */  
            12 const int map[] = {0,-1,1,-1,-1,-1,2,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3};
            13 
            14 /*
            15  * f[i][j] represent the similarity of str_a[1..i] and str_b[1..j], so:
            16  *    f[i][j] = max { f[i-1][j-1]+Score(str_a[i], str_b[j]), 
            17  *                    f[i-1][j] + Score(str_a[i], '-'),
            18  *                    f[i][j-1] + Score('-', str_b[j]) }
            19  */
            20 int
            21 dp()
            22 {
            23     int i, j, a, b, c, max;
            24     /* Attention: Initialization */
            25     table[0][0= 0;
            26     for(i=1; i<=len_a; i++)
            27         table[i][0= table[i-1][0+ Score(str_a[i], INF);
            28     for(j=1; j<=len_b; j++)
            29         table[0][j] = table[0][j-1+ Score(str_b[j], INF);
            30     
            31     for(i=1; i<=len_a; i++) {
            32         for(j=1; j<=len_b; j++) {
            33             a = table[i-1][j-1+ Score(str_a[i], str_b[j]);
            34             b = table[i-1][j] + Score(str_a[i], INF);
            35             c = table[i][j-1+ Score(INF, str_b[j]);
            36             max = a > b ? a : b;
            37             max = c > max ? c : max;
            38             table[i][j] = max;
            39         }
            40     }
            41     return table[len_a][len_b];
            42 }
            43 
            44 int
            45 main(int argc, char **argv)
            46 {
            47     int tests;
            48     scanf("%d"&tests);
            49     while(tests--) {
            50         scanf("%d %s"&len_a, str_a+1);
            51         scanf("%d %s"&len_b, str_b+1);
            52         printf("%d\n", dp());
            53     }
            54 }
            posted @ 2010-08-13 14:07 simplyzhao 閱讀(121) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1160

            思路:
            事先知道這是動態規劃的題,于是就拼命往這方面想,想啊想啊想啊想,終于靈感一現:
                  可以用f[i][j]表示到第i個村鎮為止,建造j個郵局所需要的最小距離
            心中竊喜,感覺應該挺靠譜,于是繼續深入,直覺告訴我f[i][j]與f[i-1][j], f[i-1][j-1]應該有關系,貌似成了第i個村鎮建不建郵局的子問題,繼續苦思冥想,結果卻還是想不出來。

            無奈,還是看別人的思路吧:
                  用f[i][j]表示前i個郵局建在前j個村鎮所需要的最小距離(貌似,跟我之前想的剛好相反)
                  f[i][j] = min( f[i-1][k] + cost[k+1][j],  i-1<=k<=j-1),cost[i][j]表示在村鎮i與j之間建造一個post office的最小距離(人家說顯然在中點)

            艾,差之毫厘,謬以千里,如何有效地表示和分析最優子結構是關鍵:一個問題的解,如何通過其子問題來表示和求解

            代碼:
             1 /* 752K 79MS */
             2 #include<stdio.h>
             3 #include<stdlib.h>
             4 #include<string.h>
             5 #define MAX_V 301
             6 #define MAX_P 31
             7 #define INF 0x7FFFFFFF
             8 int v, p;
             9 int pos[MAX_V];
            10 int cost[MAX_V][MAX_V];
            11 int table[MAX_P][MAX_V];
            12 
            13 void
            14 init()
            15 {
            16     int i, j, k, mid, diff;
            17     for(i=1; i<=v; i++) {
            18         for(j=i; j<=v; j++) {
            19             diff = 0;
            20             mid = (i+j)/2;
            21             for(k=i; k<=j; k++)
            22                 diff += ((pos[k]>pos[mid])?(pos[k]-pos[mid]):(pos[mid]-pos[k]));
            23             cost[i][j] = cost[j][i] = diff;
            24         }
            25     }
            26 }
            27 
            28 int
            29 dp()
            30 {
            31     int i, j, k, min, tmp;
            32     memset(table, 0sizeof(table));
            33     for(j=1; j<=v; j++)
            34         table[1][j] = cost[1][j];
            35     for(i=2; i<=p; i++) {
            36         for(j=i+1; j<=v; j++) {
            37             min = INF;
            38             for(k=i-1; k<=j-1; k++) {
            39                 tmp = table[i-1][k] + cost[k+1][j];
            40                 min = tmp<min ? tmp : min;
            41             }
            42             table[i][j] = min;
            43         }
            44     }
            45     return table[p][v];
            46 }
            47 
            48 int
            49 main(int argc, char **argv)
            50 {
            51     int i;
            52     while(scanf("%d %d"&v, &p)!=EOF) {
            53         for(i=1; i<=v; i++)
            54             scanf("%d", pos+i);
            55         init();
            56         printf("%d\n", dp());
            57     }
            58 }


            posted @ 2010-08-13 12:45 simplyzhao 閱讀(191) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1159

            思路:
            看完題目,完全不知道該怎么做
            參考discuss,發現原來DP這么這么地強大,自己那是相當菜
            設ch[1]..ch[n]表示字符串1至n位,i為左游標,j為右游標 ,則i從n遞減,j從i開始遞增。
            min[i][j]表示i和j之間至少需要插入多少個字符才能對稱,初始置全0 ,我們最終需要得到的值是min[1][n].
            則
            if(ch[i]==ch[j])                                    //如果兩個游標所指字符相同,向中間縮小范圍
                min[i][j]=min[i+1][j-1];
            else
                min[i][j] = 1 +(min[i+1][j]和min[i][j-1]中的較小值);     //如果不同,典型的狀態轉換方程
            額,狀態方程看明白了,結果發現代碼居然不知道怎么寫...那個汗哪...
            原因是沒有發現當i>j時,min[i][j] = 0

            代碼(記憶化搜索):
             1 /* Time: 1594MS */
             2 #include<stdio.h>
             3 #include<stdlib.h>
             4 #include<string.h>
             5 #define MAX_LEN 5001
             6 char str[MAX_LEN+1];
             7 int len;
             8 short memory[MAX_LEN][MAX_LEN];
             9 
            10 /*
            11  * f[i][j] represent the minimal insert for str[i..j]
            12  *
            13  * f[i][j] = f[i+1][j-1], if str[i]==str[j], otherwise
            14  * f[i][j] = min(f[i+1][j], f[i][j-1]) + 1
            15  */
            16 int
            17 func(int i, int j)
            18 {
            19     int a, b;
            20     if(i >= j)
            21         return 0;
            22     if(memory[i][j])
            23         return memory[i][j];
            24     if(str[i] == str[j])
            25         memory[i][j] = func(i+1, j-1);
            26     else {
            27         a = func(i+1, j);
            28         b = func(i, j-1);
            29         memory[i][j] = a<? a+1 : b+1;
            30     }
            31     return memory[i][j];
            32 }
            33 
            34 int
            35 main(int argc, char **argv)
            36 {
            37     while(scanf("%d"&len) != EOF) {
            38         memset(memory, 0sizeof(memory));
            39         scanf("%s", str+1);
            40         printf("%d\n", func(1, len));
            41     }
            42 }

            代碼(dp):
             1 #include<stdio.h>
             2 #include<stdlib.h>
             3 #include<string.h>
             4 #define MAX_LEN 5001
             5 char str[MAX_LEN];
             6 int len;
             7 short table[MAX_LEN][MAX_LEN];
             8 
             9 short
            10 dp()
            11 {
            12     int i, j;
            13     /* if i>j, then table[i][j] = 0 */
            14     for(i=len-1; i>=1; i--) {
            15         for(j=i; j<=len; j++) {
            16             if(str[i] == str[j])
            17                 table[i][j] = table[i+1][j-1];
            18             else
            19                 table[i][j] = table[i+1][j]<table[i][j-1? table[i+1][j]+1 : table[i][j-1]+1;
            20         }
            21     }
            22     return table[1][len];
            23 }
            24 
            25 int
            26 main(int argc, char **argv)
            27 {
            28     while(scanf("%d"&len) != EOF) {
            29         memset(table, 0sizeof(table));
            30         scanf("%s", str+1);
            31         printf("%d\n", dp());
            32     }
            33 }
            posted @ 2010-08-12 19:47 simplyzhao 閱讀(157) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=2250

            思路:
            以單詞為單位的LCS,另外需要記錄路徑信息

            代碼:
             1 #include<stdio.h>
             2 #include<stdlib.h>
             3 #include<string.h>
             4 #define MAX_NUM 101
             5 #define MAX_LEN 31
             6 char first[MAX_NUM][MAX_LEN];
             7 char second[MAX_NUM][MAX_LEN];
             8 int fcnt, scnt;
             9 int table[MAX_NUM][MAX_NUM];
            10 char path[MAX_NUM][MAX_NUM];
            11 
            12 void
            13 output(int i, int j)
            14 {
            15     if(i==0 || j==0)
            16         return;
            17     if(path[i][j] == 'u')
            18         output(i-1, j);
            19     else if(path[i][j] == 'l')
            20         output(i, j-1);
            21     else {
            22         output(i-1, j-1);
            23         printf("%s ", first[i-1]);
            24     }
            25 }
            26 
            27 void
            28 lcs()
            29 {
            30     int i, j;
            31     for(i=0; i<=fcnt; i++)
            32         table[i][0= 0;
            33     for(j=0; j<=scnt; j++)
            34         table[0][j] = 0;
            35     for(i=1; i<=fcnt; i++) {
            36         for(j=1; j<=scnt; j++) {
            37             if(strcmp(first[i-1], second[j-1]) == 0) {
            38                 table[i][j] = table[i-1][j-1+ 1;
            39                 path[i][j] = 'y';
            40             } else if(table[i-1][j] > table[i][j-1]) {
            41                 table[i][j] = table[i-1][j];
            42                 path[i][j] = 'u';
            43             } else {
            44                 table[i][j] = table[i][j-1];
            45                 path[i][j] = 'l';
            46             }
            47         }
            48     }
            49 }
            50 
            51 int
            52 main(int argc, char **argv)
            53 {
            54     while(1) {
            55         fcnt = scnt = 0;
            56         memset(table, 0sizeof(table));
            57         memset(path, 0sizeof(path));
            58         if(scanf("%s", first[fcnt++]) == EOF)
            59             break;
            60         while(scanf("%s", first[fcnt]) && first[fcnt][0]!='#')
            61             ++fcnt;
            62         while(scanf("%s", second[scnt]) && second[scnt][0]!='#')
            63             ++scnt;
            64         lcs();
            65         output(fcnt, scnt);
            66         printf("\n");
            67     }
            68 }
            posted @ 2010-08-12 15:32 simplyzhao 閱讀(137) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1953

            思路:
            如果想通了,其實就是道挺簡單的動規題
            zero_end[i]記錄第i位以0結尾的合法排列
            one_end[i]記錄第i位以1結尾的合法排列
            狀態方程即:
                             zero_end[i+1] = zero_end[i] + one_end[i]
                             one_end[i+1] = zero_end[i]
            以深度搜索的遞歸樹即可觀察得出以上結論(*^__^*) 嘻嘻……

            代碼:
             1 #include<stdio.h>
             2 #include<stdlib.h>
             3 #include<string.h>
             4 #define MAX_LEN 45
             5 int zero_end[MAX_LEN+1];
             6 int one_end[MAX_LEN+1];
             7 
             8 int
             9 build_table()
            10 {
            11     int i;
            12     zero_end[1= 1;
            13     one_end[1= 1;
            14     for(i=2; i<=45; i++) {
            15         zero_end[i] = zero_end[i-1+ one_end[i-1];
            16         one_end[i] = zero_end[i-1];
            17     }
            18 }
            19 
            20 int
            21 main(int argc, char **argv)
            22 {
            23     int i, n, tests;
            24     build_table();
            25     scanf("%d"&tests);
            26     for(i=1; i<=tests; i++) {
            27         scanf("%d"&n);
            28         printf("Scenario #%d:\n%d\n\n", i, zero_end[n]+one_end[n]);
            29     }
            30 }
            posted @ 2010-08-12 12:57 simplyzhao 閱讀(173) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1163

            思路:
            比較基礎、容易的動態規劃
            table[i][j]記錄從根節點到第i行第j個元素的最大和
            狀態轉移方程:
                         table[i][j] = max(table[i][j-1], table[i][j]) + num[i][j]

            為了節省空間,對于三角形的保存,采用了一維數組

            代碼:
             1 #include<stdio.h>
             2 #include<stdlib.h>
             3 #include<string.h>
             4 #define MAX_N 101
             5 #define MAX_LEN 5051 /* 1+2+3++100 */
             6 int rows, num[MAX_LEN];
             7 int table[MAX_N][MAX_N];
             8 
             9 /* table[i][j] = max(table[i-1][j-1]+num[i][j], table[i-1][j]+num[i][j] */
            10 int
            11 dp()
            12 {
            13     int i, j, k, tmp, max, rt;
            14     table[0][0= num[0];
            15     for(i=1; i<rows; i++) {
            16         tmp = i*(i+1)/2;
            17         for(j=0; j<=i; j++) {
            18             max = 0;
            19             for(k=1; k>=0; k--
            20                 if(j-k>=0 && j-k<=i-1/* parent index: [i-1][j-k] */
            21                     max = table[i-1][j-k]+num[tmp+j]>max ? table[i-1][j-k]+num[tmp+j] : max;
            22             table[i][j] = max;
            23         }
            24     }
            25     rt = 0;
            26     for(j=0; j<rows; j++)
            27         if(table[rows-1][j] > rt)
            28             rt = table[rows-1][j];
            29     return rt;
            30 }
            31 
            32 int
            33 main(int argc, char **argv)
            34 {
            35     int i, j, tmp;
            36     while(scanf("%d"&rows) != EOF) {
            37         for(i=0; i<rows; i++) {
            38             tmp = i*(i+1)/2;
            39             for(j=0; j<=i; j++
            40                 scanf("%d", num+(tmp+j));
            41         }
            42         memset(table, 0sizeof(table));
            43         printf("%d\n", dp());
            44     }
            45 }
            posted @ 2010-08-12 11:06 simplyzhao 閱讀(116) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=1276

            思路:
            典型的多重背包問題,參考背包九講,一次AC
            深刻理解:01背包、完全背包、多重背包

            代碼:
             1 #include<stdio.h>
             2 #include<stdlib.h>
             3 #include<string.h>
             4 #define MAX_VOLUMN 100001
             5 #define MAX_N 11
             6 #define max(a,b) ((a)>(b) ? (a) : (b))
             7 int vol, n;
             8 int cv[MAX_N], num[MAX_N], f[MAX_VOLUMN];
             9 
            10 /* f[i][v] = max(f[i-1][v], f[i-1][v-cost[i]]+value[i]) */
            11 void
            12 ZeroOnePack(int cost, int value)
            13 {
            14     int v;
            15     for(v=vol; v>=cost; v--)
            16         f[v] = max(f[v], f[v-cost]+value);
            17 }
            18 
            19 /* f[i][v] = max(f[i-1][v], f[i][v-cost[i]]+value[i]) */
            20 void
            21 CompletePack(int cost, int value)
            22 {
            23     int v;
            24     for(v=cost; v<=vol; v++)
            25         f[v] = max(f[v], f[v-cost]+value);
            26 }
            27 
            28 void
            29 MultiplePack(int cost, int value, int amount)
            30 {
            31     int k = 1;
            32     if(cost*amount >= vol)
            33         CompletePack(cost, value);
            34     else {
            35         while((amount-k) >= 0) {  
            36             ZeroOnePack(cost*k, value*k);
            37             amount -= k;
            38             k = k*2;
            39         }
            40         ZeroOnePack(cost*amount, value*amount);
            41     }
            42 }
            43 
            44 void
            45 dp()
            46 {
            47     int i;
            48     for(i=1; i<=n; i++)
            49         MultiplePack(cv[i], cv[i], num[i]);
            50 }
            51 
            52 int
            53 main(int argc, char **argv)
            54 {
            55     int i;
            56     while(scanf("%d %d"&vol, &n)!=EOF) {
            57         memset(f, 0sizeof(f));
            58         for(i=1; i<=n; i++)
            59             scanf("%d %d", num+i, cv+i);
            60         dp();
            61         printf("%d\n", f[vol]);
            62     }
            63 }
            posted @ 2010-08-11 22:03 simplyzhao 閱讀(189) | 評論 (0)編輯 收藏
            問題:
            http://acm.pku.edu.cn/JudgeOnline/problem?id=3624

            思路:
            典型的01背包問題,動態規劃,參考背包九講
            注意需要使用滾動數組,否則MLE

            代碼:
             1 #include<stdio.h>
             2 #include<stdlib.h>
             3 #include<string.h>
             4 #define MAX_N 3403
             5 #define MAX_M 12881
             6 #define max(a,b) ((a)>(b) ? (a) : (b))
             7 int n, m;
             8 /* MLE: int table[MAX_N][MAX_M]; */
             9 int table[MAX_M];
            10 int weight[MAX_N], rate[MAX_N];
            11 
            12 void
            13 dp()
            14 {
            15     int i, j;
            16     memset(table, 0sizeof(table));
            17     for(i=1; i<=n; i++)
            18         for(j=m; j>=weight[i]; j--/* Attention: descent order */
            19             table[j] = max(table[j], table[j-weight[i]]+rate[i]);
            20 }
            21 
            22 int
            23 main(int argc, char **argv)
            24 {
            25     int i;
            26     while(scanf("%d %d"&n, &m)!=EOF) {
            27         for(i=1; i<=n; i++)
            28             scanf("%d %d", weight+i, rate+i);
            29         dp();
            30         printf("%d\n", table[m]);
            31     }
            32 }
            posted @ 2010-08-11 10:57 simplyzhao 閱讀(221) | 評論 (0)編輯 收藏
                 摘要:                                                         ...  閱讀全文
            posted @ 2010-08-11 09:40 simplyzhao 閱讀(206) | 評論 (0)編輯 收藏
            僅列出標題
            共21頁: First 11 12 13 14 15 16 17 18 19 Last 

            導航

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

            統計

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久se精品一区二区| 日本免费一区二区久久人人澡| 久久精品国产精品亚洲人人 | av午夜福利一片免费看久久| 久久―日本道色综合久久| 久久伊人五月天论坛| 久久久婷婷五月亚洲97号色| 久久se这里只有精品| 久久香蕉国产线看观看精品yw| 热99re久久国超精品首页| 四虎久久影院| 日韩一区二区久久久久久 | 久久99热国产这有精品| 性欧美大战久久久久久久| 成人资源影音先锋久久资源网| 久久精品国产精品亚洲| 久久无码人妻一区二区三区午夜| 久久久久亚洲爆乳少妇无| 久久久精品一区二区三区| 日韩乱码人妻无码中文字幕久久| 国产综合精品久久亚洲| 国产Av激情久久无码天堂| 久久国产色av免费看| 亚洲午夜精品久久久久久app| 9999国产精品欧美久久久久久| 亚洲中文字幕无码久久精品1| 久久人人爽人爽人人爽av | 天天爽天天狠久久久综合麻豆| 午夜精品久久久久久影视777| 99久久国产亚洲高清观看2024 | 久久综合狠狠综合久久| 97香蕉久久夜色精品国产| 久久久久亚洲精品男人的天堂| 伊人久久精品线影院| 国产国产成人精品久久| 综合久久国产九一剧情麻豆| 亚洲欧洲中文日韩久久AV乱码| 久久国产免费| 久久亚洲av无码精品浪潮| 久久精品?ⅴ无码中文字幕| 精品久久久久中文字幕一区|