首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【动态规划】【 数学】C++算法:514自由之路

  • 24-03-11 13:09
  • 3418
  • 13359
blog.csdn.net

作者推荐

【动态规划】458:可怜的小猪

涉及知识点

动态规划 数学

力扣514 自由之路

电子游戏“辐射4”中,任务 “通向自由” 要求玩家到达名为 “Freedom Trail Ring” 的金属表盘,并使用表盘拼写特定关键词才能开门。
给定一个字符串 ring ,表示刻在外环上的编码;给定另一个字符串 key ,表示需要拼写的关键词。您需要算出能够拼写关键词中所有字符的最少步数。
最初,ring 的第一个字符与 12:00 方向对齐。您需要顺时针或逆时针旋转 ring 以使 key 的一个字符在 12:00 方向对齐,然后按下中心按钮,以此逐个拼写完 key 中的所有字符。
旋转 ring 拼出 key 字符 key[i] 的阶段中:
您可以将 ring 顺时针或逆时针旋转 一个位置 ,计为1步。旋转的最终目的是将字符串 ring 的一个字符与 12:00 方向对齐,并且这个字符必须等于字符 key[i] 。
如果字符 key[i] 已经对齐到12:00方向,您需要按下中心按钮进行拼写,这也将算作 1 步。按完之后,您可以开始拼写 key 的下一个字符(下一阶段), 直至完成所有拼写。
示例 1:
输入: ring = “godding”, key = “gd”
输出: 4
解释:
对于 key 的第一个字符 ‘g’,已经在正确的位置, 我们只需要1步来拼写这个字符。
对于 key 的第二个字符 ‘d’,我们需要逆时针旋转 ring “godding” 2步使它变成 “ddinggo”。
当然, 我们还需要1步进行拼写。
因此最终的输出是 4。
示例 2:
输入: ring = “godding”, key = “godding”
输出: 13
提示:
1 <= ring.length, key.length <= 100
ring 和 key 只包含小写英文字母
保证 字符串 key 一定可以由字符串 ring 旋转拼出

动态规划

** 时间复杂度 ** : O(nmm) n=key.length m等于一个字符在ring中出现的次数。
三层循环:
一层循环枚举key的字符。
二层循环当前字符的位置。
三层循环前一个字符的位置。

两个表盘位置,逆时针和顺时针最少需要转动的次数。
iMin=min(i1,i2) iMax = max(i1,i2)
min(iMax-iMin,iMin+ring.length-iMax)

动态规划的细节,方便检查

动态规划的状态表示pre中的元素{prePos,preSetp} 按完上一个字符后,金属盘所在的位置和需要步数。
动态规划的转移方程枚举当前字符位置和前一字符位置,计算最小值
动态规划的初始状态{0,0}
动态规划的填表顺序key从前到后处理,确保动态规划的无后效性
动态规划的返回值max(preStep)

代码

核心代码

class Solution {
public:
	int findRotateSteps(string ring, string key) {
		vector<vector<int>> vCharIndexs(26);
		for (int i = 0; i < ring.length(); i++)
		{
			vCharIndexs[ring[i] - 'a'].emplace_back(i);
		}
		vector<pair<int, int>> pre;
		pre.emplace_back(0, 0);
		for (const auto& ch : key)
		{
			vector<pair<int, int>> dp;
			const auto& cur = vCharIndexs[ch - 'a'];
			for (const auto& curPos : cur)
			{
				int curStep = INT_MAX;
				for (const auto [prePos, step] : pre)
				{
					const int iMin = min(prePos, curPos), iMax = max(prePos, curPos); 
					curStep = min(curStep, step + 1 +  min(iMax - iMin, iMin + (int)ring.length() - iMax));
				}
				dp.emplace_back(curPos, curStep);
			}
			pre.swap(dp);
		}
		int iRet = INT_MAX;
		for (const auto [prePos, step] : pre)
		{
			iRet = min(iRet, step);
		}
		return iRet;
	}
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{
	assert(t1 == t2);
}

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		Assert(v1[i], v2[i]);
	}
}


int main()
{
	string ring,  key;

	{
		Solution sln;
		ring = "godding", key = "gd";
		auto res = sln.findRotateSteps(ring, key);
		Assert(4, res);
	}
	{
		Solution sln;
		ring = "godding", key = "godding";
		auto res = sln.findRotateSteps(ring, key);
		Assert(13, res);
	}
	
		
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

2023年1月版

class Solution {
public:
int findRotateSteps(string ring, string key) {
std::unordered_map mCharPos;
for (int i = 0; i < ring.length(); i++)
{
mCharPos[ring[i]].push_back(i);
}
std::unordered_map vPrePosOpeNum;//当前位置及最少操作次数
vPrePosOpeNum[0] = 0;
for (const char& ch : key)
{
std::unordered_map vPosOpeNum;
for (const auto& pos : mCharPos[ch])
{
for (const auto& prePos : vPrePosOpeNum)
{
//大的减小的
int iMove = abs(prePos.first - pos);
iMove = min(iMove,min(prePos.first, pos) + (int)ring.length() - max(prePos.first, pos));
const int iOpeNum = iMove + prePos.second + 1;
if (vPosOpeNum.count(pos))
{
vPosOpeNum[pos] = min(vPosOpeNum[pos], iOpeNum);
}
else
{
vPosOpeNum[pos] = iOpeNum;
}
}
}
vPrePosOpeNum.swap(vPosOpeNum);
}
int iMin = INT_MAX;
for (const auto& prePos : vPrePosOpeNum)
{
iMin = min(iMin, prePos.second);
}
return (INT_MAX == iMin) ? -1 : iMin;
}
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修

改问题,给老板节约钱。|
| 子墨子言之:事无终始,无务多业

。也就是我们常说的专业的人做专业的事。 |
|如果程序是一条龙,那算法就是他的是睛|

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 **C+

+17**
如无特殊说明,本算法用**C++**实现。

群中有博文配套源码
QQ群名片
注:本文转载自blog.csdn.net的闻缺陷则喜何志丹的文章"https://blog.csdn.net/he_zhidan/article/details/135510577"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top