• HDU


    Problem Description

    The twenty-first century is a biology-technology developing century. We know that a gene is made of DNA. The nucleotide bases from which DNA is built are A(adenine), C(cytosine), G(guanine), and T(thymine). Finding the longest common subsequence between DNA/Protein sequences is one of the basic problems in modern computational molecular biology. But this problem is a little different. Given several DNA sequences, you are asked to make a shortest sequence from them so that each of the given sequence is the subsequence of it.

    For example, given "ACGT","ATGC","CGTT" and "CAGT", you can make a sequence in the following way. It is the shortest but may be not the only one.

    Input

    The first line is the test case number t. Then t test cases follow. In each case, the first line is an integer n ( 1<=n<=8 ) represents number of the DNA sequences. The following k lines contain the k sequences, one per line. Assuming that the length of any sequence is between 1 and 5.

    Output

    For each test case, print a line containing the length of the shortest sequence that can be made from these sequences.

    Sample Input

    1 4 ACGT ATGC CGTT CAGT

    Sample Output

    8

    题意:

    从n个串中找出一个最短的公共串,,该公共串对于n个字符串不要求连续,即只要保持相对顺序就好。

    思路:

    用迭代加深搜索,所谓迭代加深搜索,就是限制DFS的深度,若搜不到答案,则加深深度,重新搜索,这样就防止了随着深度不断加深而进行的盲目搜索,而且,对于这种求最短长度之类的题目,只要找到可行解,即是最优解了。同时注意剪枝,每次DFS的时候,都要判断一下,当前的深度+最少还有加深的深度是否大于限制的长度,若是,则退回上一层状态。

    #include<bits/stdc++.h>
    using namespace std;
    
    char str[10][10];//记录n个字符串
    int n, ans, deep, Size[10];
    char DNA[4] = { 'A','C','G','T' };//4种可能性
    
    void dfs(int cnt,int len[]) {
        if (cnt > deep)return;//大于了最大深度
        int maxx = 0;//预计还要匹配的字符串的最大长度
        for (int i = 0; i < n; ++i) {
            int t = Size[i] - len[i];
            if (t > maxx)
                maxx = t;
        }
        if (maxx == 0) {//条件全部满足即为最优解
            ans = cnt; return;
        }
        if (cnt + maxx > deep)return;
        for (int i = 0; i < 4; ++i) {
            int pos[10], flag = 0;
            for (int j = 0; j < n; j++)
            {
                if (str[j][len[j]] == DNA[i])
                {
                    flag = 1;
                    pos[j] = len[j] + 1;
                }
                else
                    pos[j] = len[j];
            }
            if (flag)
                dfs(cnt + 1, pos);
            if (ans != -1)
                break;
        }
    }
    
    int main() {
        int T;
        cin >> T;
        while (T--) {
            cin >> n;
            int maxn = 0;
            for (int i = 0; i < n; ++i) {
                cin >> str[i];
                Size[i] = strlen(str[i]);
                if (Size[i] > maxn)
                    maxn = Size[i];
            }
            ans = -1; deep = maxn;
            int pos[10] = { 0 };//记录n个字符串目前匹配到的位置
            while (1) {
                dfs(0, pos);
                if (ans != -1)break;
                ++deep;
            }
            cout << ans << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    中医手诊原理
    半月痕
    0020 教您新手修车的五种实用技巧
    下面说说我开车12年来的一些心得
    创建电子邮件信纸
    交通事故责任划分2011版(图解)
    育儿语录
    汽车中控台那些按钮是什么用的?
    我的书中的部分函数
    纠结的书名
  • 原文地址:https://www.cnblogs.com/RioTian/p/13110340.html
Copyright © 2020-2023  润新知