pku_1699_Best Sequence

 

pku_1699_Best Sequence

 

 

【题目概述】求NN<=10)个子串的最短和串,且不会发生一个完全包涵另外一个的现象。

【题目分析】简单的状态DP问题,一开始想用字符串的思想解决,发现状态之间,不好变换。正好自己做压缩DP的专题,还是,用这个方法吧!

1.         对于每个字符串的放置,和她有直接影响的是上一个字符的放置情况。由此,我们可以建立一个状态转移方程

 表示当前状态s以第i个字符串结尾产生的最小和串的长度。则

2.         s只包含一个串的时候, 其中len[i]表示第i个子串的长度。

3.         否则,如果当前的状态合法,且s状态集中,不包含有j串,那么,

a)        如果 其中,com[I, j] 表示第i个串之后是第j个串的公共子串的长度。

b)        否则,不处理。

4.         最后的结果就是,    i是所有的子串。

【题目代码】:

//Name: pku_1699_Best Sequence

#include <iostream>

#include <cstring>

using namespace std;

const int inf = 1<<20;

const int maxn = 1<<10;

char str[10][20];

int len[10], com[20][20], n, m;

int dp[maxn][10], ans;

void Link(int x, int y) {

    int i, j, k, mlen = min(len[x], len[y]);

    for (k = mlen; k >= 0; k--) {

        for (i = len[x]-k, j = 0; i < len[x]; i++, j++)

            if (str[x][i] != str[y][j]) break;

        if (i == len[x]) {

            com[x][y] = k; break;

        }

    }

    for (k = mlen; k >= 0; k--) {

        for (i = len[y]-k, j = 0; i < len[y]; i++, j++)

            if (str[y][i] != str[x][j]) break;

        if (i == len[y]) {

            com[y][x] = k; break;

        }

    }

}        

int main() {

   // freopen("in.in", "r", stdin);

    int t, i, j, s, r; scanf("%d", &t);

    while(t-- && scanf("%d", &n)) {

        memset(com, 0, sizeof(com));

        for(i = 0; i < n; i++) {

             scanf("%s", str+i);

             len[i] = strlen(str[i]);

             for (j = 0; j < i; j++) Link(i, j);

        }

       // for(i = 1; i < n; i++) printf("%d\n", com[i-1][i]);

        for(i = 1; i < 1<<n; i++)

            for (j = 0; j < n; j++) dp[i][j] = inf;

        for(i = 0; i < n; i++) dp[1<<i][i] = len[i];

        for(s = 1; s < 1<<n; s++) {

            for (i = 0; i < n; i++) if(s&(1<<i)) {

                for(j = 0; j < n; j++) if(i!=j && !(s&(1<<j))) {

                    r = s|(1<<j);

                    dp[r][j] = min(dp[r][j], dp[s][i] - com[i][j] + len[j]);

                  // printf("dp[%d][%d] = %d\n", r, j, dp[r][j]);

                 }

             }

        }

     // for(i = 0; i < n; i++) printf("%d\n", dp[s-1][i]);

        ans = inf;

        for(i = 0; i < n; i++)

            if (dp[s-1][i] < ans) ans = dp[s-1][i];

        printf("%d\n", ans);

   }

   return 0;

}

       

posted on 2010-08-08 16:05 小志 阅读(285) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年8月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
2930311234

导航

统计

常用链接

留言簿

随笔档案(8)

文章档案(1)

相册

收藏夹

ACM --- Online Judge

小志

最新随笔

积分与排名

最新随笔

最新评论

阅读排行榜

评论排行榜