HDU 1560 DNA sequence

HDU_1560

    一种可行的思路是迭代加深搜索,只要在不断增加递归深度限制时第一次出现生成了规定的字符串时,这个深度就是最优的深度了。

    接下来就是考虑如何剪枝了,一种明显的思路就是记录当前每个字符串还差多少位补全,然后取最大的差距,如果剩下的可以构造的字符数小于最大的差距的话,那么就可以剪枝了。但这个剪枝还不够强,比如这个数据就会很慢

8
AAAAA
GGGGG
CCCCC
TTTTT
TTTAA
AAATT
CCGGG
GGGCC

,根据这个数据就会想到一个更好的剪枝,我们考虑至少还需要多少个A,至少还需要多少个T以及C、G,然后把4项之和作为前面所说的“最大的差距”,用这个作为剪枝的条件就比较快了,上面那组数据就几乎瞬出了。

    至于至少需要多少个A,我们可以先算一下各个字符串还需要多少个A,然后取最大值,至于T、C、G也是一样的。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 8
#define MAXL 5
int N, n[MAXN], a[MAXN][MAXL];
char ch[128];
void init()
{
    int i, j;
    char b[10];
    scanf("%d", &N);
    for(i = 0; i < N; i ++)
    {
        scanf("%s", b);
        n[i] = strlen(b);
        for(j = 0; j < n[i]; j ++) a[i][j] = ch[b[j]];
    }
}
int Max(int *x)
{
    int i, j, h[4], max[4] = {0};
    for(i = 0; i < N; i ++)
    {
        memset(h, 0, sizeof(h));
        for(j = x[i]; j < n[i]; j ++) ++ h[a[i][j]];
        for(j = 0; j < 4; j ++) max[j] = std::max(max[j], h[j]);
    }
    return max[0] + max[1] + max[2] + max[3];
}
int dfs(int d, int *ix)
{
    if(Max(ix) > d) return 0;
    if(d == 0) return 1;
    int i, j, x[MAXN];
    for(i = 0; i < 4; i ++)
    {
        for(j = 0; j < N; j ++)
        {
            if(ix[j] < n[j] && a[j][ix[j]] == i)
                x[j] = ix[j] + 1;
            else x[j] = ix[j];
        }    
        if(dfs(d - 1, x)) return 1;
    }
    return 0;
}
void solve()
{
    int dep, ini[8] = {0};
    for(dep = 1; !dfs(dep, ini); dep ++);
    printf("%d\n", dep);
}
int main()
{
    int t;
    ch['A'] = 0, ch['T'] = 1, ch['C'] = 2, ch['G'] = 3;
    scanf("%d", &t);
    while(t --)
    {
        init();
        solve();    
    }
    return 0;    
}

 

 

 

你可能感兴趣的:(sequence)