ACWING 190. 字串变换(双向bfs)

2024-04-16 02:18
文章标签 bfs 双向 acwing 变换 190 字串

本文主要是介绍ACWING 190. 字串变换(双向bfs),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

已知有两个字串 A, B 及一组字串变换的规则(至多6个规则):

A1 -> B1
A2 -> B2

规则的含义为:在 A 中的子串 A1 可以变换为 B1、A2 可以变换为 B2 …。

例如:A=’abcd’ B=’xyz’

变换规则为:

‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’

则此时,A 可以经过一系列的变换变为 B,其变换的过程为:

‘abcd’->‘xud’->‘xy’->‘xyz’

共进行了三次变换,使得 A 变换为B。

输入格式
输入格式如下:

A B
A1 B1
A2 B2 |-> 变换规则
… … /

所有字符串长度的上限为 20。

输出格式
若在 10 步(包含 10步)以内能将 A 变换为 B ,则输出最少的变换步数;否则输出”NO ANSWER!”

输入样例:
abcd xyz
abc xu
ud y
y yz
输出样例:
3

思路: 膜着yxc dalao的代码写的。没想到是双向bfs。
也就是说,对于字符串A,B。A->B的过程来一次bfs,B->A的过程来一次bfs,两次bfs的结果综合起来,相加就是结果。

1 中间相加结果大于10就退出
2 每次取队顶(也就是变换值最小的次数)的较小的那一半,进行处理。
3 初始化da[A] = 0, db[B] = 0,中间到了队顶的字符串,枚举每一位可以进行什么样的交换。然后用map记录对应字符串的交换值相加就是结果(注意当前对应哪个字符串)。

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#include <queue>using namespace std;int n;
string aa[10],bb[10];int solve(queue<string> &q,map<string,int> &da,map<string,int> &db,string a[],string b[])
{string t = q.front();q.pop();for(int i = 0;i < t.size();i++){for(int j = 1;j <= n;j++){if(t.substr(i,a[j].size()) != a[j])continue;string r = t.substr(0,i) + b[j] + t.substr(i + a[j].size());if(db.count(r))return db[r] + da[t] + 1;if(da.count(r))continue;da[r] = da[t] + 1;q.push(r);}}return -1;
}int bfs(string x,string y)
{queue<string>qa,qb;map<string,int>da,db;qa.push(x);da[x] = 0;qb.push(y);db[y] = 0;while(qa.size() && qb.size()){if(da[qa.front()] + db[qb.front()] > 10)return 11;int res;if(da[qa.front()] < db[qb.front()])res = solve(qa,da,db,aa,bb);else res = solve(qb,db,da,bb,aa);if(res != -1)return res;}return 11;
}int main()
{string A,B;cin >> A >> B;n = 1;while(cin >> aa[n] >> bb[n])n++;n--;int ans = bfs(A,B);if(ans <= 10)printf("%d\n",ans);else printf("NO ANSWER!\n");return 0;
}

这篇关于ACWING 190. 字串变换(双向bfs)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/907559

相关文章

hdu1254(嵌套bfs,两次bfs)

/*第一次做这种题感觉很有压力,思路还是有点混乱,总是wa,改了好多次才ac的思路:把箱子的移动当做第一层bfs,队列节点要用到当前箱子坐标(x,y),走的次数step,当前人的weizhi(man_x,man_y),要判断人能否将箱子推到某点时要嵌套第二层bfs(人的移动);代码如下:

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

poj 2195 bfs+有流量限制的最小费用流

题意: 给一张n * m(100 * 100)的图,图中” . " 代表空地, “ M ” 代表人, “ H ” 代表家。 现在,要你安排每个人从他所在的地方移动到家里,每移动一格的消耗是1,求最小的消耗。 人可以移动到家的那一格但是不进去。 解析: 先用bfs搞出每个M与每个H的距离。 然后就是网络流的建图过程了,先抽象出源点s和汇点t。 令源点与每个人相连,容量为1,费用为

POJ 3057 最大二分匹配+bfs + 二分

SampleInput35 5XXDXXX...XD...XX...DXXXXX5 12XXXXXXXXXXXXX..........DX.XXXXXXXXXXX..........XXXXXXXXXXXXX5 5XDXXXX.X.DXX.XXD.X.XXXXDXSampleOutput321impossible

深度优先(DFS)和广度优先(BFS)——算法

深度优先 深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支,当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访

Verybot之OpenCV应用二:霍夫变换查找圆

其实我是想通过这个程序来测试一下,OpenCV在Verybot上跑得怎么样,霍夫变换的原理就不多说了,下面是程序: #include "cv.h"#include "highgui.h"#include "stdio.h"int main(int argc, char** argv){cvNamedWindow("vedio",0);CvCapture* capture;i

react笔记 8-19 事件对象、获取dom元素、双向绑定

1、事件对象event 通过事件的event对象获取它的dom元素 run=(event)=>{event.target.style="background:yellowgreen" //event的父级为他本身event.target.getAttribute("aid") //这样便获取到了它的自定义属性aid}render() {return (<div><h2>{

【AcWing】851. 求最短路

spfa算法其实是对贝尔曼福特算法做一个优化。 贝尔曼福特算法会遍历所有边来更新,但是每一次迭代的话我不一定每条边都会更新,SPFA是对这个做优化。 如果说dist[b]在当前这次迭代想变小的话,那么一定是dist[a]变小了,只有a变小了,a的后继(b)才会变小。 用宽搜来做优化,用一个队列,队列里边存的就是所有变小了的结点(队列里存的是待更新的点)。 基本思路就是我更新过谁,我再拿

双头BFS

牛客月赛100 D题,过了80%数据,调了一下午。。。烦死了。。。 还是没调试出来,别人的代码用5维的距离的更新有滞后性,要在遍历之前要去重。。。 #include<bits/stdc++.h>using namespace std;const int N=2e3+10;char g[N][N];int dis[N][N],d1[N][N];int n,m,sx,sy;int dx

Knight Moves -uva 简单的BFS遍历

昨天刚学了BFS的遍历,在uva上找了个题敲了出来,感觉还不错,最近敲代码挺有手感的,希望这种状态保持下去 #include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX_SIZE 10 + 5#define LEN 100 + 10using namespace std;in