题目链接:DNA sequence HDU - 1560
===================================================
DNA sequence
Time Limit: 5000MS
Memory Limit: 32768 kB
Description
The twenty-first century is a biology-technology developing century. We know that a gene is made of DNA. The nucleotide bases from which DNA is built are A(adenine), C(cytosine), G(guanine), and T(thymine). Finding the longest common subsequence between DNA/Protein sequences is one of the basic problems in modern computational molecular biology. But this problem is a little different. Given several DNA sequences, you are asked to make a shortest sequence from them so that each of the given sequence is the subsequence of it.
For example, given “ACGT”,“ATGC”,“CGTT” and “CAGT”, you can make a sequence in the following way. It is the shortest but may be not the only one.
Input
The first line is the test case number t. Then t test cases follow. In each case, the first line is an integer n ( 1<=n<=8 ) represents number of the DNA sequences. The following k lines contain the k sequences, one per line. Assuming that the length of any sequence is between 1 and 5.
Output
For each test case, print a line containing the length of the shortest sequence that can be made from these sequences.
Sample Input
1
4
ACGT
ATGC
CGTT
CAGT
Sample Output
8
===================================================
算法:IDA* dfs
思路:
- 题目大意就是给出一堆字符串序列,然后求一个包含这些字符串序列的最小字符串长度。
- 每一步进行字符串末尾添加,然后对那些需要包含的字符串用数组记录剩余长度。长度为0,则结束。最优估算剩余步数就是字符串中剩余最长长度。
- limit开始使用被包含字符串最大长度,然后逐步最小增加。
===================================================
#include <iostream>
#include <cstring>
#include <string.h>
#include <algorithm>
#include <cstdio>
using namespace std;
const int INF = 2e9;
int n,nextd,limit;
string s[9];
char ch[5] = "ACGT";
bool IDAstar(int step,int limit,int *len){
int h = 0;
for(int i=0;i<n;i++) {int fk = s[i].length() - len[i];h = max(fk,h);}
if(h==0) { cout<<step<<endl; return true;}
if(h+step>limit) {nextd = min(nextd, h+step);return false;}
for(int i=0;i<4;i++){
bool flag = false;
int tnt[9];
for(int j=0;j<n;j++)
if(ch[i] == s[j][len[j]]){
flag = true;
tnt[j] = len[j] + 1;
}else tnt[j] = len[j];
if(flag&&IDAstar(step+1,limit,tnt)) return true;
}
return false;
}
int main()
{
int _;cin>>_;
while(_--){
cin>>n;
limit = 0;
int len[9] = {0};
for(int i=0;i<n;i++) {
cin>>s[i];
int fk = s[i].length();
limit = max(limit,fk);
}
//for(int i=0;i<n;i++) cout<<s[i]<<endl;
while(1){
nextd = INF;
if(IDAstar(0,limit,len)) break;
limit = nextd;
}
}
return 0;
}
===================================================
拓展思考:这题如果直接给出一个目标字符串,然后允许你插入,移动字符串直到全包含。感觉题目就难一点了。
难点在于增加了任意位置插入字符操作,而不是简单的末尾添加,并且你可以移动,相当于位置替换。
现在我还没想到怎么最优解…等哪一天想到;或者做得类似题目就补上。