HDU-1560

#include <bits/stdc++.h>
using namespace std;

int t;
int n;
int depth; // 深度
string str[10]; // DNA序列数组
int pos[10]; // 当前每个DNA匹配到的位置
char dna[4] = { 'A', 'T', 'C', 'G' }; // 四种碱基

bool ida(int now) {
    // 剪枝
    int maxlen = 0;
    for (int i = 0; i < n; i++)
        maxlen = max(maxlen, (int)(str[i].size() - pos[i]));
    if (now - 1 + maxlen > depth)
        return false;
    // 成功条件:当前深度达到限制且所有序列都已匹配完
    if (now == depth + 1 && maxlen == 0)
        return true;
    // 开始dfs 遍历四种碱基 每种更新pos数组
    int originalPos[10]; // 保存当前匹配位置
    for (int i = 0; i < 4; i++) {
        memcpy(originalPos, pos, sizeof(pos)); // 保存当前状态
        for (int j = 0; j < n; ++j) {
            // 更新每个序列的匹配位置
            if (dna[i] == str[j][pos[j]]) {
                pos[j]++; // 说明和当前位置匹配上了 匹配下一个
            }
        }
        if (ida(now + 1))
            return true;
        // 回溯
        memcpy(pos, originalPos, sizeof(pos)); // 回溯,恢复到之前的状态
    }
    return false;
}

int main() {
    cin >> t;
    while (t--) {
        cin >> n;
        // 初始化
        depth = 0; // 重置深度
        for (int i = 0; i < n; i++) {
            cin >> str[i];
            if (depth < str[i].size())
                depth = (int)str[i].size();
        }
        // 开始迭代加深搜索
        while (true) {
            memset(pos, 0, sizeof(pos));
            if (ida(1)) { // 从深度1开始
                cout << depth << endl;
                break;
            }
            depth++;
        }
    }

    return 0;
}

经过参考各方大佬的代码 和自己的理解 我才勉勉强强能理解本题的方法:

使用IDA*:迭代dfs+剪枝 首先读取每一个字符串 然后选择最大长度作为初始深度 每次迭代+1 设置三个数组: dna序列数组 当前匹配数组 最短dna序列数组 剪枝: 剩余匹配数组的最大值小于深度-当前dna序列的长度 每次dfs都更新当前匹配数组

本题我根据大佬的代码做了一些改动 使用pos[]全局变量作为记录当前追踪过程 每次遍历完后回溯

做了几道IDA*的题发现关键还是求最小代价作为剪枝是关键

其次就是dfs遍历的原理 逻辑一定要严谨 不能有疏漏 再接再厉吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值