集训作业 洛谷P1032 字串变换

集训的题目有点多,先写困难的绿题吧(简单的应该想想就会了)

嗯,这个题看起来像个搜索呢(就是个搜索)

我们仔细想想就知道这个题肯定不能用深搜,可以优化的地方太少了,TLE是必然的。

那我们该怎么办呢?

很简单,用选代加深啊,我真是个睿(弱)智的小孩。

一遍自认为很强大的选代加深后:

嗯,放弃了。

明显以我的能力驾驭不了选代加深,优化不够……

我只能用优化力度更大的广搜了。

什么?为啥早不用?我说了,我是个睿(弱)智的小孩。

广搜可以用的优化更多了,有一个神奇的东西叫做记忆化,广搜有个特点,如果这个点之前曾经查询到过,那这次用的步数就一定比上次少。我们定义一个数组表示来过没有,曾经来过就可以停下了。如果你不知道“这次用的步数就一定比上次少”是为什么的话就戳这里

好了,该用什么搜索已经定了,该解决一下第二恶心的东西了。

字符串,一个新手的噩梦(我看见了都恶心)

但这个题竟然让我们匹配字符串(对于我这种渣渣简直毫无人性),没办法,只能硬上了。

我们来愉快的模拟吧。具体代码后面一起贴出来吧。

代码出现了:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue> 
#include<map>
using namespace std;
string n,m,gb;
long long w,t,shu,bj,bss;
string as,jc;
queue<string>s;
queue<int>bs;
map<string,int>mp;
struct hehe
{
	string a,b;
	long long cd;
}sz[10];
bool pd(int x,int y,string mb,string yl)//这就是我们的判断环节,x和y是开始和结束节点,y是故意大了一个的。
{
  //mb是目标,就是看看原来的字符串x到y-1位是不是和条件对应(理解成脏话的同学要考虑一下自己的品德哦),yl当然就是原来的意思啦。
	jc="";
	for(int i=x;i<y;i++)
	{
		jc+=yl[i];//把要对比的一段取出来
	}
	if(jc==mb)//是一样的,可以替换。
	{
		return true;
	}
}
void pj(int x,int y,string mb,string yl)//刚才替换成功了,现在要来看看替换完之后的字符串是什么。
{
	jc="";//又是jc,我也忘了为啥叫jc了,可能因为他不重要
	for(int i=0;i<x;i++)
	{
		jc+=yl[i];//替换的前面
	}
	jc+=mb;//替换的部分
	for(int i=y;i<yl.length();i++)
	{
		jc+=yl[i];//替换的后面
	}
	//成品jc出炉 
	return;
}
void bfs()//喜闻乐见的广搜环节
{
	while(s.empty()!=true)//还有路,不要放弃
	{
		as=s.front();//来看看这次在哪里
		bss=bs.front();//走到这里用了多少步
		if(as==m)//哎呀到地方了。
		{
			bj=1;
			cout<<bss<<endl;//嗯,我一共走了bss步。
			return;
		}
		for(int i=0;i<shu;i++)//额,又没走到,看看下一步有什么情况可以走。
		{
			for(int j=0;j+sz[i].cd-1<as.length();j++)//如果接下来的数量不够我换,那就不走了。
			{
				if(pd(j,j+sz[i].cd,sz[i].a,as)==true&&bss!=10)//我是可以换的,而且移动次数也没到10步。换吧
				{
					pj(j,j+sz[i].cd,sz[i].b,as);//来获取一下我该变成什么样子的
					if(mp[jc]==0)//他没出现过哎,这是第一次来,存进去
					{
						mp[jc]=1;//现在他出现了
						s.push(jc);
						bs.push(bss+1);//走到变成现在前一步用了bss步,再走一步,自然就是bss+1啦。
					}
				}
			}
		}
		s.pop();//别忘了删除掉哦,这可是一次性用品
		bs.pop();
	}
}
int main()
{
	cin>>n>>m;
	mp[n]=1;//这个是map,也就是记忆化数组。
	s.push(n);//储存所有下一步可移动地点的队列s
	bs.push(0);//储存对应操作步数的队列bs
	while(cin>>sz[shu].a>>sz[shu].b)//一个神奇的方法,输入Ctrl+Z就可以停止了(这是一个大佬教我的,他叫FUXyao)
	{
		sz[shu].cd=sz[shu].a.length();//一会准备匹配用的长度
		shu++;
	}
	bfs();
	if(bj==0)//不可能到达目标。
	{
		cout<<"NO ANSWER!"<<endl;
	}
	return 0;
}

代码一如既往的臭长,希望同学们谅解。

如果有不明白的地方,可以评论在下面,我会更改的。

 

posted @ 2020-05-13 21:13  lichangjian  阅读(163)  评论(0编辑  收藏  举报