2021 ICPC沈阳 J.Luggage Lock(bfs,模拟)

题目描述

题目链接

题目分析

这 是 一 道 很 明 显 的 b f s + 模 拟 的 题 ( 和 八 数 码 是 一 类 题 ) 这是一道很明显的bfs+模拟的题(和八数码是一类题) bfs+

因 为 起 点 和 终 点 都 不 一 样 , 还 有 1 e 5 个 测 试 样 例 。 因 此 不 能 直 接 对 每 一 组 样 例 都 做 一 遍 b f s , 肯 定 会 超 时 。 因为起点和终点都不一样,还有1e5个测试样例。因此不能直接对每一组样例都做一遍bfs,肯定会超时。 1e5bfs

因 此 我 们 可 以 将 所 有 测 试 样 例 的 起 点 都 转 化 为 0000 , 终 点 对 应 变 为 t [ i ] − s [ i ] ( s 为 起 点 , t 为 终 点 ) 因此我们可以将所有测试样例的起点都转化为0000,终点对应变为t[i]-s[i](s为起点,t为终点) 0000t[i]s[i]st

这 样 转 换 之 后 , 我 们 可 以 以 0000 作 为 起 点 进 行 一 遍 b f s , 同 时 记 录 下 到 达 每 个 状 态 所 需 的 步 数 。 这 样 对 于 这样转换之后,我们可以以0000作为起点进行一遍bfs,同时记录下到达每个状态所需的步数。这样对于 0000bfs 每 个 测 试 样 例 即 可 O ( 1 ) 输 出 答 案 。 每个测试样例即可O(1)输出答案。 O(1)

代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <algorithm>
#include <iomanip>
#define LL long long
#define ULL unsigned long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define PDD pair<double,double>
#define x first
#define y second
using namespace std;
const int N=1e5+5,mod=1e9+7;
map<string,int> f;				//用map记录到达每个状态的步数
void bfs()
{
	queue<string> q;
	q.push("0000");				//“0000”为起点
	f["0000"]=0;
	while(q.size())
	{
		auto u=q.front();
		q.pop();
		string a,b;
		for(int i=0;i<4;i++)			//枚举每一个区间[i,j]
			for(int j=i;j<4;j++)
			{
				a=b=u;
				for(int k=i;k<=j;k++)
				{
					a[k]=(u[k]-'0'+1)%10+'0';		//a记录u在[i,j]区间内+1得到的状态
					b[k]=(u[k]-'0'+9)%10+'0';		//b记录u在[i,j]区间内-1得到的状态
				}
				if(f.find(a)==f.end())		//如果f中没有a状态,则将其放入队列
				{
					q.push(a);
					f[a]=f[u]+1;
				}
				if(f.find(b)==f.end())		//同上
				{
					q.push(b);
					f[b]=f[u]+1;
				}
			}
	}
}
int main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);
	bfs();					//bfs预处理出所有答案
	int T;
	cin>>T;
	while(T--)
	{
		string s,t;
		cin>>s>>t;				//将起点转化为0000,终点变为t[i]-s[i]
		for(int i=0;i<4;i++) t[i]=(t[i]-s[i]+10)%10+'0';
		cout<<f[t]<<endl;		//输出答案
	}
	return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwz_159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值