zoukankan      html  css  js  c++  java
  • 字串变换

    字串变换

    https://www.luogu.com.cn/problem/P1032

    前言:

    NOIp提高组2002的一道字符串+广搜题,还是有难度的

    因为你首先得通过题意分析出这是一道广搜,然后还要在编程中避开所有的坑(手动狗头)

    题目简述:

    给定初始字符串A和目标串B,以及不多于6个的变换规则

    要求求出将A变成B的最少步骤数,如果步骤数在10步以内(包含10步)就输出答案,否则输出“NO ANSWER!”


    解题思路:

    (1)首先分析一下为什么是广搜题,题意变换一下:

    给定初始位置和目标位置,以及不多于6个的移动方向(变换规则),要求求出从初始到目标的最少步数

    这不就是明摆的广搜嘛!?

    (2)分析出了广搜,那最基础的代码思路也就成型了:

    ①首先将输入的规则存入两个数组中,一个存变化前一个存变化后

    以A为出发点开始广搜,对于每一个队首字符串,我们开双层循环枚举它的每一个位置,再枚举每一种变换规则

    ③然后进入处理变换的函数change中,首先判断改变后的字符串是否合法,合法的话就进行改变并返回压入队尾

    (3)再来讲一下change函数,判断是否合法主要是两个条件

    ①改变后的字符串长度大于队首字符串的长度,不合法

    ②改变后的字符和规则不相等,不合法

    注意:将以上的思路转换为代码之后,提交上去,你就会发现,你要么T了3、5要么RE了3、5,反正只有60pts。所以就有了如下的第四步优化操作:

    (4)设置一个map<string,int> 数组,每处理了一个字符串就标记一下(其实就相当于普通广搜标记当前位置是否走过),这样判重以后,你就A掉了这个题


    代码Code:

    PS:主程序中用/**/括起来的代码是用来检查样例能不能对用的

    #include <bits/stdc++.h>
    using namespace std;
    int n,ans;
    string A,B,gz[1001],gzs[1001];
    map<string,int> shan; //shan这个map数组用来剪枝判重
    
    struct node {
    	string word;
    	int st;
    } q[100001];
    
    inline string change(string tmp,int x,int y) { //改变字符串 
    	string sum="";
    	if(gz[y].length()+x>tmp.length()) return sum; //判断是否合法 
    	for(register int i=0;i<gz[y].length();i++) {
    		if(tmp[x+i]!=gz[y][i]) return sum;
    	}
    	sum=tmp.substr(0,x); //substr,string的函数,下面会补充介绍 
    	sum+=gzs[y];
    	sum+=tmp.substr(x+gz[y].length());
    	return sum;
    }
    
    inline void bfs(string a) {
    	int front=1,tail=1;
    	q[front].word=a;
    	q[front].st=0;
    	while(front<=tail) {
    		for(register int i=0;i<q[front].word.length();i++) { //枚举当前对头字符串的每一个位置 
    			for(register int j=0;j<n;j++) { //再枚举每一种转换手段 
    				string now=change(q[front].word,i,j);
    				if(now!=""&&shan[now]!=1) { //如果变换后的字符串合法且没有处理过,就入队 
    					tail++;  
    					q[tail].word=now;
    					q[tail].st=q[front].st+1; //累加步数 
    					shan[now]=1;
    					if(now==B) { //如果到达了B就输出步数 
    						ans=q[tail].st;
    						return ;
    					}
    				}
    			}
    		}
    		front++;
    	}
    }
    
    int main() {
    	cin>>A>>B;
    /*	n=3;
    	for(register int i=0;i<n;i++) {
    		cin>>gz[i]>>gzs[i]; 
    	}*/
    	while(cin>>gz[n]>>gzs[n]) n++; //一直输入规则 
    	bfs(A); //以字符串A为起点开始广搜 
    	if(ans>10||ans==0) puts("NO ANSWER!"); 
    	else printf("%d",ans);
    	return 0;
    }
    

    补充一下:

    substr(pos,len)返回从pos号位开始、长度为len的子串,时间复杂度为O(len)

    吐槽一下:直接输出“NO ANSWER!”可以得到20pts....没加判重的BFS一般是40-60pts不等


  • 相关阅读:
    Oracle数据库安装
    [转]卡西欧手表调日期正确方法
    python密码处理(可用于生产模式)
    [转]python对json的相关操作
    [转]Python中的with…as…
    Python标准库--os模块
    我的github代码添加
    Python正则表达式+自创口诀
    自己总结python用xlrdxlwt读写excel
    CentOS安装+配置+远程
  • 原文地址:https://www.cnblogs.com/Eleven-Qian-Shan/p/13099530.html
Copyright © 2011-2022 走看看