NOJ [1307] English Magic 字符串转化 3种操作 加1 减1 交换相邻字符

  • [1307] English Magic

  • 时间限制: 2000 ms 内存限制: 65535 K
  • 问题描述
  • XP's English is very poor! He will read A into ah! Now he needs you to do him a favor! Now he gives you two same length string s1 and s2, and you should use some rules change s1 into s2
    Each time, you can add or minus 1 to any character.( When add 1 to 'z', the character will change to be 'a' and when minus 1 to 'z', the character will change to be 'a')
    You can also exchange the character with its neighbor. Each action will take one step. Now your task is to tell XP the minimal steps to transform.
  • 输入
  • There are many cases.
    Each test case contain two strings s1 and s2.It guarantee s1's length equal to s2's length and the length of the string will not exceed 5.
  • 输出
  • For each test case, print the minimal steps in one line
  • 样例输入
  • aaa
    bbb
    
    aoxz
    oaxa
    
  • 样例输出
  • 3
    2
  • 提示
  • The first case:aaa->baa->bba->bbb 
    The second case: aoxz->oaxz->oaxa 
  • 来源
  • 加多宝凉茶
  • 操作
  • hnust_xiehonghao

     

    给你两个长度相同的小写字母字符串(长度不超过 5),你可以对第一个字符串进行以下操作:

    1.交换相邻两个字母。
    2.对其中一个字母进行加一操作。(z 加一为 a)
    3.对其中一个字母进行减一操作。(a 减一为 z)
    求第一个字符串需要几次操作才能变成第二个字符串。

     

     

    思路:

    BFS

    一个状态代表从字符串一只经过交换操作得到的字符串以及其所需要的操作数。

    接下去把第一个字符串入队。

    每从队列中获取一个状态我们都做如下操作:

    1.对于这个状态,它的步数就是状态中的步数加上每个字母只通过加减操作得到目标串的步数。

    2.将这个状态的各位置相邻字母交换,每种位置交换得到一个新状态,当前步数加一,然后入队。

    然后对于每次生成新状态,都检验一下这个状态的字符串是否已经出现过,若没出现过则可以不入队了。

     

    #include<stdio.h>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<queue>
    #include<map>
    using namespace std;
    char s1[10],s2[10];
    struct haha
    {
    	string str;
    	int step;
    }temp,q;
    int ans,len;
    map<string,bool>mp;
    int mmin(int a,int b)
    {
    	if(a>b) return b;
    	return a;
    }
    int dis(string &p)//求2字符串进行字符加1减1操作需要进行的次数
    {
    	int cnt=0,i;
    	for(i=0;i<len;i++)
    	{
    		int mid=abs(p[i]-s2[i]);
    		mid=mmin(mid,26-mid);
    		cnt+=mid;
    	}
    	return cnt;
    }
    void BFS()
    {
         int i,j;
    	 q.step=0;
    	 q.str=s1;
    	 queue<struct haha> que;
    	 que.push(q);
    	 while(!que.empty())
    	 {
    		 temp=que.front();
    		 que.pop();
    		 if(ans<=temp.step)   continue;
    		 ans=mmin(ans,temp.step+dis(temp.str));
    		 for(i=0;i<temp.str.length()-1;i++)
    		 {
    			 string s=temp.str;
    			  char c=s[i+1];
    			  s[i+1]=s[i];
    			  s[i]=c;
    			  q.step=temp.step+1;
    			  q.str=s;
    			  if(mp.find(q.str)==mp.end())
    			  {
    				  que.push(q);
    				  mp[q.str]=true;
    			  }
    		 }
    
    
    	 }
    	 printf("%d\n",ans);
    }
    int main()
    {
    	while(scanf("%s %s",s1,s2)!=EOF)
    	{
    		mp.clear();
              len=strlen(s1);
    		  ans=999999999;
              BFS();
    	}
    	return 0;
    }


     

    小疑惑:  为什么只用交换得到状态 然后用2个字符串相加1减1得到的操作数作为结果那

    难道不会有可能使得加1减1后 然后进行交换  得到新状态 这时候字符串再相加减得到的距离更短那

    求大神指教啊!!!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值