HDU - 1560 DNA sequence 【迭代加深】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1560

关于迭代加深,可以参考这篇博客 https://blog.csdn.net/hzaukotete/article/details/81226556

迭代加深是在dfs的基础上,枚举深搜的深度 dep。

比如说 我一开始规定 dep == 1,当dfs深搜到深度为 1的时候就回溯,如果dep == 1没有找到答案,那么就让dep+1,继续从头开始深搜,当深度到2的时候就回溯。以此类推,直到找到答案时,dep就是我们要求的答案。也就是说,设置的dep是不管找没找到答案,到了规定的深度dep就回溯。

这种深搜有点类似bfs。

此外迭代加深的搜索一定要有一个比较有效的剪枝方法来减少搜索的次数。

最常用的方法是设置一个估计值,这个估计值不需要太精确,大概估计即可,如果这个估计值超出了规定的dep,那么就不必要做dfs了,直接dep++,以此来减少dfs的搜索次数。

思路:

枚举每一位可能出现的字母。

如样例1,给每一个字符串都设置一个指针,初始指向第一位,如果设置第一个字母为A,那么把所有指针指向的字母为A的指针都后移一位,然后继续枚举第二个字母。直到所有的指针都指向最末尾的时候,就能得到答案。

这里迭代深搜的估计方法也很简单,要想找到答案,设置的dep最起码要等于或者大于字符串最长的那个字符串的长度。同样的,在搜索的过程中,要想找到答案,当前步数step + 指针距离末尾最长的长度 <= dep。

#include <iostream>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int INF = 0x3f3f3f3f;
const int Maxn = 4e5+10;

struct Q {
    int num[10], p, cur;
} qu[10];

int N, dep, ans;

void dfs(int step) {
    bool vis[10], mark[10];
    int maxn = 0;

    for(int i = 0; i < N; ++i) {
        maxn = max(maxn, qu[i].p-qu[i].cur);
    }
    if(maxn == 0) {
        ans = step; return;
    }
    if(maxn+step > dep) return;

    memset(vis, false, sizeof(vis));
    memset(mark, false, sizeof(mark));

    for(int i = 0; i < N; ++i) {
        if(qu[i].cur == qu[i].p) continue;
        int tmp = qu[i].num[qu[i].cur];

        if(vis[tmp]) continue;
        vis[tmp] = true;

        for(int j = 0; j < N; ++j) {
            if(qu[j].cur == qu[j].p) continue;
            if(qu[j].num[qu[j].cur] == tmp) {
                qu[j].cur++; mark[j] = true;
            }
        }
        dfs(step+1);
        if(ans != -1) return;
        for(int j = 0; j < N; ++j) {
            if(mark[j]) {
                qu[j].cur--; mark[j] = false;
            }
        }
    }
}

int main(void)
{
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &N);
        char str[10];
        for(int i = 0; i < N; ++i) qu[i].cur = qu[i].p = 0;
        for(int i = 0; i < N; ++i) {
            scanf("%s", str);
            for(int j = 0; j < strlen(str); ++j) {
                if(str[j] == 'A') qu[i].num[qu[i].p++]= 1;
                else if(str[j] == 'C') qu[i].num[qu[i].p++]= 2;
                else if(str[j] == 'G') qu[i].num[qu[i].p++]= 3;
                else if(str[j] == 'T') qu[i].num[qu[i].p++]= 4;
            }
        }
        ans = -1; dep = 1;
        while (ans == -1) {
            dfs(0); dep++;
        }
        printf("%d\n", ans);
    }
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值