HUST 1605 Gene recombination

23 篇文章 0 订阅

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 integer  N 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

直接广搜容易超时和爆内存,我这里使用了位运算和map存储。

#include<cstdio>
#include<vector>
#include<map>
#include<queue>
#include<string>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
char ch[maxn];
int n, s, t;

int get(char ch)
{
	return ch == 'A' ? 0 : ch == 'T' ? 1 : ch == 'C' ? 2 : 3;
}

int main()
{
	while (scanf("%d", &n) != EOF)
	{
		scanf("%s", ch);	s = t = 0;
		for (int i = 0; i < n; i++) s = (s << 2) | get(ch[n - i - 1]);
		scanf("%s", ch);
		for (int i = 0; i < n; i++) t = (t << 2) | get(ch[n - i - 1]);
		if (!(s ^ t)) { printf("0\n"); continue; }
		queue<int> p;	p.push(s);	
		map<int, int> M;	M[s] = 0;
		int a = ((1 << n << n) - 1) ^ 15, b = 3, c = 12;
		while (!p.empty())
		{
			int q = p.front();	p.pop();
			int x = (q >> 2) | ((q & b) << n + n - 2);
			int y = (q & a) | (q & b) << 2 | (q & c) >> 2;
			int d = M[q] + 1;
			if (x == t || y == t) { printf("%d\n", d); break; }
			if (!M[x]) { M[x] = d; p.push(x); }
			if (!M[y]) { M[y] = d; p.push(y); }
		}
	}
	return 0;
}
如果不用map,而是直接用bool来表示状态的情况的话,速度会快很多

#include<cstdio>
#include<vector>
#include<map>
#include<queue>
#include<string>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1 << 24;
bool vis[maxn];
char ch[15];
int n, s, t;

int get(char ch)
{
	return ch == 'A' ? 0 : ch == 'T' ? 1 : ch == 'C' ? 2 : 3;
}

struct point
{
	int x, y;
	point(int x = 0, int y = 0) :x(x), y(y){};
};

int main()
{
	while (scanf("%d", &n) != EOF)
	{
		scanf("%s", ch);	s = t = 0;
		for (int i = 0; i < n; i++) s = (s << 2) | get(ch[n - i - 1]);
		scanf("%s", ch);
		for (int i = 0; i < n; i++) t = (t << 2) | get(ch[n - i - 1]);
		if (!(s ^ t)) { printf("0\n"); continue; }
		memset(vis, 0, sizeof(vis));
		queue<point> p;	 p.push(point(s, 0));	vis[s] = true;
		int a = ((1 << n << n) - 1) ^ 15, b = 3, c = 12;
		while (!p.empty())
		{
			point q = p.front();	p.pop();
			int x = (q.x >> 2) | ((q.x & b) << n + n - 2);
			int y = (q.x & a) | (q.x & b) << 2 | (q.x & c) >> 2;
			if (x == t || y == t) { printf("%d\n", q.y + 1); break; }
			if (!vis[x]) { vis[x] = true; p.push(point(x, q.y + 1)); }
			if (!vis[y]) { vis[y] = true; p.push(point(y, q.y + 1)); }
		}
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值