POJ 1699 Best Sequence (DFS+预处理)

题意:看那张图就一清二楚了吧, N个序列首位相连(相同的序列部分),得到最短的总序列。

题目链接:http://poj.org/problem?id=1699

~~~~

思路就是:将N个序列首尾相连能重合的长度求粗来。然后DFS枚举每种首尾相连的情况。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 22
#define INF 0x7fffffff
using namespace std;

int n,ans;
int f[N][N],vis[N],len[N];
char str[N][N];
void get(int x,int y)  //f[x][y],将y贴到x后面能减少的最大重复长度
{
    int i,j,l;
    for(l=len[y];l>0;l--)   //枚举长度
    {
        int ok=1;
        for(i=len[x]-l,j=0;i<len[x] && j<len[y];i++,j++)
        {
            if(i<0)    //~~
            {
                ok=0;
                break;
            }
            if(str[x][i]!=str[y][j])
            {
                ok=0;
                break;
            }
        }
        if(ok)
        {
            f[x][y]=l;
            return ;
        }
    }
    f[x][y]=0;
}
void dfs(int x,int s,int tot)
{
    if(s==n)
    {
        ans=min(ans,tot);
        return ;
    }
    if(tot>ans)    //剪枝~
        return ;
    for(int i=0;i<n;i++)
    {
        if(!vis[i])
        {
            vis[i]=1;
            dfs(i,s+1,tot+len[i]-f[x][i]);  //~~
            vis[i]=0;
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%s",str[i]);
            len[i]=strlen(str[i]);
        }
        memset(f,0,sizeof(f));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(i==j) continue;
                else get(i,j);
            }
        }
        ans=INF;
        for(int i=0;i<n;i++)    //dfs枚举每种首尾相连的方法。
        {
            vis[i]=1;
            dfs(i,1,len[i]);
            vis[i]=0;
        }
        printf("%d\n",ans);
    }
    return 0;
}

POJ 1699 Best Sequence (DFS+预处理),布布扣,bubuko.com

时间: 2024-10-22 17:37:21

POJ 1699 Best Sequence (DFS+预处理)的相关文章

poj 1699 Best Sequence(dfs)

http://poj.org/problem?id=1699 题意:给出n个只含A,C,G,T的字符串,要求能把这n个字符串组合起来的最短长度. 思路:预处理一下,a[i][j]表示将第j个字符串连接到第i个字符串后面增加的长度,那么我们需要找出这样一个序列1,2....n满足a[1][2] + a[2][3] + ...+a[n-1][n]的最小值.DFS就OK了,任选一个字符串作为起点进行dfs,求出所有的情况后得到最小的长度. #include <stdio.h> #include &l

POJ 1699 Best Sequence(DFS)

題目鏈接 題意 : 將幾個片段如圖所示方法縮成一個序列,求出最短這個序列. 思路 : 其實我也不知道怎麼做.....看網上都用了DP.....但是我不會.....這個DP不錯,還有用KMP+状压DP做的 1 //1699 2 #include <iostream> 3 #include <stdio.h> 4 #include <string.h> 5 #include <string> 6 7 using namespace std; 8 9 string

poj 1699 Best Sequence (搜索技巧 剪枝 dfs)

题目链接 题意:给出几个基因片段,要求你将它们排列成一个最短的序列,序列中使用了所有的基因片段,而且不能翻转基因. 分析:先计算出add数组,再dfs枚举. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <cstdio> 6 #include <vector> 7 #include <al

poj 1699 Best Sequence

http://poj.org/problem?id=1699 题意:给你n个长度为L的序列,求包含这几个序列的最短长度. 先预处理每两个序列之间的关系,然后dfs枚举就行. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 500 5 using namespace std; 6 const int inf=1<<30; 7 8 char str[ma

poj 1699 Best Sequence(AC自动机+状压DP)

题目链接:poj 1699 Best Sequence 题目大意:给定N个DNA序列,问说最少多长的字符串包含所有序列. 解题思路:AC自动机+状压DP,先对字符串构造AC自动机,然后在dp[s][i]表示匹配了s,移动到节点i时候的最短步数. #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <iostream> #include &

POJ 1019 Number Sequence 题解

这又是一道看似简单,实际挺困难的题目. 本来想做道基础题消遣一下的,没想到反被消遣了-_-|||. 看个人的基础吧,对于数学好的会简单点,但是由于情况太多,需要都考虑全,故此难度应该在4星以上了. 我这里使用的方法就是直接打表,然后直接模拟,利用打表去掉一大段数据,剩下数据量十分小了,故此可以直接模拟. 打表是为了计算前面的周期数,把周期数直接去掉. 主要难点是后面10位数以上的数有2位, 3位,4位等情况要考虑.- 下面使用getNewNums一个函数解决了,想通了,就几行代码,还不用难理解的

POJ 3411 Paid Roads(dfs)

*注:这一题很重要的是对与数据的处理和细节的把握把! http://poj.org/problem?id=3411 题目大意: 有n个城市,m条路,(0<=n,m<=10).从a到b,如果之前已经经过c点,那么付费p,否者付费r.求最小的费用,从1-->n! 注意: There may be more than one road connecting one city with another. so:你不能用map[a][b]存a->b的距离.只能有road [ i ]了. 还有

POJ 1321 棋盘问题 --- DFS

POJ 1321 棋盘问题 http://poj.org/problem?id=1321 /*POJ 1321 棋盘问题 --- DFS*/ #include <cstdio> #include <cstring> int n, k, cnt; bool visit[10]; //标记列的访问状态 char mapp[10][10]; /*从第r行开始正确放置p个棋子*/ void dfs(int r, int p){ if (p == 0){ ++cnt; return; } i

uva1626 poj 1141 Brackets Sequence 区间dp 打印路径

// poj 1141 Brackets Sequence // 也是在紫书上看的一题,uva就是多了一个t组数据. // 经典区间dp // dp(i,j)表示区间[i,j]内所需要增加的括号数目 // 则分为两种情况 // 一种是s[i]和s[j]是匹配的则 // dp[i][j] = min(dp[i][j],dp[i+1][j-1]) // 另外一种情况是不匹配 // dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]){i<k<j}; // 但是无