华中电子科技大学 oj hust1605 Gene recombination 数字代表字符串的状态解决MLE

该博客讲述了如何解决一个基因重组问题,其中涉及到对基因序列进行特定操作以达到目标序列的最小操作次数。问题包括两种操作:交换前两个字母或把第一个字母移到末尾。通过BFS和优先队列来解决这个问题,以避免超时和内存溢出。
摘要由CSDN通过智能技术生成

Gene recombination

Time Limit: 2 Sec   Memory Limit: 64 MB
Submissions: 78   Solved: 9

Description

As a gene engineer of a gene engineering project, Enigma encountered a puzzle about gene recombination. It is well known that a gene can be considered as a sequence, consisting of four nucleotides, which are simply denoted by four letters, A, C, G, and T.
Enigma has gotten a gene, such as "ATCC". And he wants to reorder this gene to make a new one, like "CTCA". He can use two types of operations: (1) exchange the first two letters, or (2) move the first letter to the end of the gene. For example, "ATCC" can be changed to "TCCA" by operation (2), and then "TCCA" can be changed to "CTCA" by operation (1). Your task is to make a program to help Enigma to find out the minimum number of operations to reorder the gene.

Input

The input contains several test cases. The first line of a test case contains one integerN indicating the length of the gene (1<=N<=12). The second line contains a string indicating the initial gene. The third line contains another string which Enigma wants.
Note that the two strings have the same number for each kind of letter.

Output

For each test case, output the minimum number of operations.

Sample Input

4
ATCC
CTCA
4
ATCG
GCTA
4
ATCG
TAGC

Sample Output

2
4
6

HINT

Source

Problem Setter : Jian He

题意:

一个初始串 一个目标串 问从初始到目标串最少需要几次操作

已知 有2中操作  1 最前面的2个字符互相交换    2   第一个字符放到最后一个字符后面去

共有 CGAT   四种字符    且字符串最长为12



思路: 我参考了标程才有了思路 哎  技术不够啊  要加油了

4^12=10^6级别  可以直接BFS+优先队列 找到最小次数   关键是如何解决超时以及爆内存  很好的题目

#include <stdio.h>
#include <string.h>
#include<queue>
using namespace std;
const int maxn = 12;
const int maxk = 4;
int n,st_num,ed_num;
char f[369600];
int list [369600];
int head , tail , len , oldlen;
int st[maxn], ed[maxn];
struct haha
{
	int num;
	int step;
	friend bool operator<(haha a,haha b)
	{
		return a.step>b.step;
	}
}temp,q;
int tonum(int a[])//字符串压缩成一个数字
{
	int i;
	int re = 0;
	for(i=0;i<n;i++)
	{
		re = re * maxk + a[i];
	}
	return re;
}
void tostr(int re, int a[])//把一个数字还原为字符串
{
	int i;
	for(i=n-1;i>=0;i--)
	{
		a[i] =re%maxk;
		re /= maxk;
	}
}
int sum0 , c0[maxk];
int sum , c[maxk];
int toHash(int a[]){//hash  用来标记是否出现过某个数字  用vis数组会爆内存
	int i,j;
	int re = 0;
	sum = sum0;
	memcpy(c, c0, sizeof(c));
	for(i=0;i<n;i++){
		for(j=0;j<a[i];j++)if(c[j]){
			re += sum * c[j] / (n-i);
		}
		sum = sum * c[a[i]] / (n-i);
		c[a[i]]--;
	}
	return re;
}
int toC(char c)//把输入时的字符串变成数字串
{
	if(c=='A')return 0;
	else if(c=='T') return 1;
	else if(c=='C') return 2;
	return 3;
}
int BFS()//BFS暴力搜索
{
	int mid,s1[13],s2[13];
	int i;
	int  num;
	priority_queue<struct haha>que;
	q.num=st_num;
	q.step=0;
	que.push(q);
	f[toHash(st)] = 1;
	while(!que.empty())
	{
	
		temp=que.top();
		que.pop();
		if(ed_num==temp.num) return temp.step;
		tostr(temp.num,s1);
		mid=s1[0];
		s1[0]=s1[1];
		s1[1]=mid;
		q.step=temp.step+1;
		
        num=tonum(s1);
		if(f[toHash(s1)] != 1)
		{
			f[toHash(s1)]=1;
		q.num=num;
        que.push(q);
		}
        	
	    tostr(temp.num,s2);
		mid=s2[0];
		for(i=0;i<n-1;i++)
		s2[i]=s2[i+1];
		s2[n-1]=mid;
		q.step=temp.step+1;
		num=tonum(s2);
	    if(f[toHash(s2)]!=1)
		{
			f[toHash(s2)]=1;
		q.num=num;
        que.push(q);
		}
	}
	return 0;

}
int main() {
	int i,j;
	char stmp[20];
	while(scanf("%d",&n)==1 && n){
		scanf("%s",stmp);
		for(i=0;i<n;i++){
			st[i] = toC(stmp[i]);
		}
		scanf("%s",stmp);
		for(i=0;i<n;i++){
			ed[i] = toC(stmp[i]);
		}
		memset(c0, 0, sizeof(c0));
		sum0 = 1;
		for(i=0;i<n;i++)c0[st[i]]++,sum0*=(i+1);
		for(i=0;i<maxk;i++)for(j=0;j<c0[i];j++)
			sum0 /= (j+1);
		memset(f, 0, sizeof(char)*sum0);
		f[toHash(st)] = 1;
		st_num = tonum(st);
		ed_num = tonum(ed);
		if(st_num==ed_num){
			printf("0\n");
			continue;
		}
		printf("%d\n", BFS());
	}
	return 0;
}



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值