DNA sequence HDU 1560

   写了有段时间搜索题目,但是第一次碰到迭代深搜。

这是题目链接

题目的意思大概就是给你几个字符串让后让你求包含所有这几个字符串的最短字符串。不要求连续只要相对位置不变就可以

这道题我没有用广搜写过,好像是会MLT。

思路就是对照着“ACGT”,不一定要这个只要包含这四个字母的序列,用一个q数组存每一个字符串当前还没放进去的第一位的位置

然后依次拿输入中的几个字符串的第一位没有被放进去的字符去匹配,如果相同就让搜索深度加一,并且当前字符串的q++.直到深度超过当前规定的最大深度或者所有字符串的q都已经等于字符串的长度;

              ida的特点就是先规定一个深度,如果超过了这个深度还没找到答案就让这个最大深度加一然后再搜。这样就避免了这道题里一直往下搜搜一些完全不必要的点。

还有两种剪枝。我认为这个博客剪枝讲的很清楚

http://blog.csdn.net/flyawayl/article/details/55667822

        以下是自己写的代码,剪枝部分是学习上面这个博客的代码的

代码的最后给了两个测试数据,看看就好,是我自己乱打的。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <cmath>
#include <map>
using namespace std;
int deepmax;
int ans;
int n;
int tp[4], coast[4];
map<char, int> ha;
string sub = "ACGT";
string s[10];

int cal(int pos[])
{
    memset(tp, 0, sizeof(tp));
    memset(coast, 0, sizeof(coast));
    int ans = 0;
    for(int i = 0; i < n; ++i)      //遍历每一个字符串
    {
        for(int j = pos[i]; j < s[i].length(); ++j)++tp[ha[s[i][j]]];  //记录第i个字符串中各种字符的数量
        for(int j = 0; j < 4; ++j)
        {
            coast[j] = max(coast[j], tp[j]);        //记录每种sub中的字符在每个字符串中出现的次数的最大的一个次数
            tp[j] = 0;      //初始化
        }
    }
    for(int j = 0; j < 4; ++j)ans += coast[j];      //计算出最少还要多深的层数
    return ans;
}

bool DFS(int index, int len[])
{
    int maxx = -1;
    maxx = cal(len);
    if(maxx == 0)       //如果最少只需要0说明已经搜到了
    {
        ans = index;
        cout << ans<<endl;
        return true;
    }
    if(index + maxx > deepmax)return false;  //如果预计的最少深度都超出的话就可以退出了
    int pos[10] = {0};          //初始化
    for(int i = 0; i < n; ++i)
    {
        pos[i] = len[i];
    }
    int flag = false;
    for(int i = 0; i < 4; ++i)
    {
        for(int j = 0; j < n; ++j)
        {
            if(sub[i] == s[j][pos[j]])      //如果当前字符串有和sub[i]相同的就让当前字符串的pos++;
            {
                ++pos[j];
                flag = true;
            }
        }
        if(flag && DFS(index + 1, pos)) //如果没有相同的就不要往下搜了,这个flag不判断貌似也能ac,不知道到底有没有用,看所有网上的代码都有这个条
        {
            return true;
        }
        else
        {
            for(int j = 0; j < n; ++j)
            {
                pos[j] = len[j];        //还原
            }
        }
    }
    return false;
}



int main()
{
    for(int i = 0; i < 4; ++i)
    {
        ha[sub[i]] = i;             //剪枝的时候统计当前字符串里有几个sub[i]用的
    }
    int t;
    cin >>t;
    int pos[10];        //记录第i个字符串已经放进了几个字符
    while(t--)
    {
        deepmax = -1;     //规定最大搜索深度
        memset(pos, 0, sizeof(pos));
        cin >>  n;
        for(int i = 0; i < n; ++i)
        {
            cin >>s[i];
            if(deepmax < s[i].length())deepmax = s[i].length();  //找最长的字符串作为初始最大搜索深度
        }
        while(1)
        {
            ans = -1;           //标记是否找到
            DFS(0, pos);
            if(ans != -1)break;      //其实我这里如果dfs返回bool类型的话我可以直接用dfs的返回值判断是否已经搜到了答案。
            ++deepmax;      //没有找到就让最大搜索深度加一
            //cout <<'D'<<deepmax<<endl;
        }
    }
    return 0;
}
/*
66
5
ACGT
TACG
TGCA
AAAA
CGAG
6
AACG
GCAT
TAGC
GCTT
ACGT
ACAC

8
AAAAA
CCCCC
TTTTT
GGGGG
CACAC
AGGGA
TTTTT
GAGGA

10

10

20
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值