HUST-1605 - Gene recombination 广搜

1605 - Gene recombination

时间限制:2秒 内存限制:64兆
364 次提交 83 次通过
题目描述
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.
输入
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.
输出
For each test case, output the minimum number of operations.
样例输入
4
ATCC
CTCA
4
ATCG
GCTA
4
ATCG
TAGC
样例输出
2
4
6
提示
来源
Problem Setter : Jian He

题意:输入一个数字,代表下面的两串字符串的长度,第一个字符串表示原始串,第二个字符串表示目标串,允许对原始串进行两种操作:一种是交换前两个字母的位置,另一种是将第一个字母放到字符串的末尾。问至少经过多少次操作能够讲原始串变为目标串。

解析:因为需要求出的操作数必须是最小的,所以使用广搜(BFS),可以确保搜索到目标状态时的操作数一定是最少。另外,如果对每个搜索过程中的状态用字符串进行存储的话,会超出限定内存(MLE),因此需要使用四进制或者五进制(根据个人习惯选择),因为只有四种字母,可以将每个字母对应不同的数字,例如:A=0,C=1,G=2,T=3,根据这个规则将状态转化成四进制表示的一个数(ATCC即为四进制下的0311),然后将这个数字转成十进制存储下来,这样一来每个状态都对应一个数值,大大减少了内存的消耗,我们只需判断当前状态的数值与目标态是否相同,就等同于在判断当前串是否与目标串相同。搜索过程中,使用map进行访问标记,如果不进行标记,程序容易陷入死循环。

根据以上的思路,然后写成代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
int m2,n;
char a[15],b[15];
map<int ,int> vis;
pair<map<int,int>::iterator,bool> flag;

struct State
{
    int num;
    int step;
};

int bfs(State st)
{
    vis.clear();
    queue <State> q;
    State now,next;
    st.step=0;
    vis.insert(pair<int,int>(st.num,0));
    q.push(st);
    int j;
    while(!q.empty())
    {
        now=q.front();
        if(now.num==m2)
        {
            return now.step;
        }
        for(int i=0; i<2; i++)
        {
            int tmp=now.num;
            if(i==0)//ex
            {
                next.num=0;
              for(int j=0;j<n-2;j++)
              {
                next.num+=tmp%4*pow(4,j);
                tmp/=4;
              }
              next.num+=tmp%4*pow(4,n-1);
              tmp/=4;
              next.num+=tmp%4*pow(4,n-2);
            }
           else if(i==1)//to the end
            {
               next.num=0;
              for(int j=1;j<=n-1;j++)
              {
                next.num+=tmp%4*pow(4,j);
                tmp/=4;
              }
              next.num+=tmp;
            }
            flag=vis.insert(pair<int,int>(next.num,0));

            if(flag.second)
            {
            next.step=now.step+1;
            q.push(next);
            }
        }
        q.pop();
    }
    return -1;
}
int main()
{
    int m1,i;
    State st;
    while(~scanf("%d",&n))
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        scanf("%s",&a);
        scanf("%s",&b);
        m1=m2=0;
        for(i=0;i<n;i++)
        {
            int tp;
            if(a[i]=='A') tp=0;
            else if(a[i]=='C') tp=1;
            else if(a[i]=='G') tp=2;
            else if(a[i]=='T') tp=3;
            m1=m1*4+tp;
            if(b[i]=='A') tp=0;
            else if(b[i]=='C') tp=1;
            else if(b[i]=='G') tp=2;
            else if(b[i]=='T') tp=3;
            m2=m2*4+tp;
        }
        st.num=m1;
        printf("%d\n",bfs(st));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值