HDU 1560 DNA sequence

HDU 1560 DNA sequence

21世纪可是生物科技大放异彩的时代!我们都知道基因是由DNA构成的,而DNA则由四种核苷酸碱基组成:A(腺嘌呤)、C(胞嘧啶)、G(鸟嘌呤)和T(胸腺嘧啶)。在现代计算分子生物学中,寻找DNA/蛋白质序列的最长公共子序列是个经典问题。不过今天这道题有点特别——给定若干DNA序列,你需要构造出一个最短的新序列,使得每个给定序列都是它的子序列。

举个栗子🌰,给定"ACGT"、"ATGC"、"CGTT"和"CAGT",你可以这样构造新序列(虽然不一定唯一,但保证是最短的):

img

输入

第一行是测试用例数量t。接着t个测试用例,每个用例第一行是整数 \(n\) \((1≤n≤8)\)表示DNA序列数量,随后n行每行一个DNA序列(保证每个序列长度在1到5之间)。

输出

对每个测试用例,输出一行表示能构造出的最短序列长度。

样例

\(Input\) \(Output\)
1
4
ACGT
ATGC
CGTT
CAGT
8

题解

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N = 10;
int T,n,deep;
string DNA[N],ans = " ",spi[4] = {"A","G","C","T"};
int fin[N],tmp[N],siz[N],cnt[N],index[N*3];
int h(){
	memset(tmp,0,sizeof(tmp));
	for(int i=1;i<=n;i++){
		for(int j=fin[i]+1;j<=siz[i];j++) cnt[index[DNA[i][j]-'A']]++;
		for(int j=0;j<4;j++) tmp[j] = max(tmp[j],cnt[j]),cnt[j] = 0;
	}
	int res = 0;
	for(int i=0;i<4;i++) res += tmp[i];
	return res; 
}
bool IDAStar(int step){
	int est = h();
	if(!est) return true;
	if(step+est>deep) return false;
	int rec[N];
	for(int i=0;i<4;i++){
		memcpy(rec,fin,sizeof(fin));
		bool flag = 0;
		for(int j=1;j<=n;j++){
			if(DNA[j][fin[j]+1]==spi[i][0]){
				fin[j]++;
				flag = 1;
			}
		}
		if(flag && IDAStar(step+1)) return true;
		memcpy(fin,rec,sizeof(rec));
	}
	return false;
}
void init(){
	memset(fin,0,sizeof(fin));
	deep = 0;
}
signed main(){
	cin>>T;
	for(int i=0;i<4;i++) index[spi[i][0]-'A'] = i;
	while(T--){
		init();
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>DNA[i];
			siz[i] = DNA[i].size();
			DNA[i] = " " + DNA[i];
			deep = max(deep,siz[i]);
		}
		while(!IDAStar(0)) deep++;
		cout<<deep<<'\n';
	}
	return 0;
}

使用下一位未匹配进行估价。

注意到这里对比前后状态的方法很有趣,新建数组然后复制下来。

\(END\)

posted @ 2025-06-02 22:24  OrangeRED  阅读(30)  评论(0)    收藏  举报