#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遍历的原理 逻辑一定要严谨 不能有疏漏 再接再厉吧