【C++学习笔记】密码转盘锁解题,记录开锁步骤

1 篇文章 0 订阅
//本程序是对照leetcode 找到岛屿而写的
//加入队列回查功能,将各个节点都进行保留
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<queue>
#include <unordered_set>
using namespace std;

class Solution {

public:
	string plus_one(string str, int index)
	{
		if (str[index] == '9')
			str[index] = '0';
		else
		{
			str[index] = str[index] + 1;
		}
		return str;
	}

	string down_one(string str, int index)
	{
		if (str[index] == '0')
			str[index] = '9';
		else
		{
			str[index] = str[index] - 1;
		}
		return str;
	}

	int openLock(vector<string>& deadends, string target) {
		unordered_set<string> deadset(deadends.begin(), deadends.end());
		const string finnal_target(target);
		queue<string>q;
		vector<queue<string>> que_Pre ;//上次的队列容器
		vector<queue<string>> que_Now;//这次经过扩增之后的队列容器
		q.push("0000");
		que_Now.push_back(q);
		unordered_set<string>visited;
		visited.insert("0000");
		int step = 0;
		while (!q.empty())
		{
			que_Pre = que_Now;   //将上一次结果进行转存
			que_Now.clear();  //将当前的路径进行清除操作
			int queue_size = q.size();
			for (size_t i = 0; i < queue_size; i++)
			{
				string str_cnw = q.front();
				q.pop();
				if (deadset.find(str_cnw) != deadset.end())
				{//找到了不能经过的死路,那么就continue大循环
					continue;
				}
				if (str_cnw.compare(finnal_target) == 0)
				{
					for (size_t i = 0; i < que_Pre.size(); i++)
					{
						if (que_Pre[i].back().compare(finnal_target) == 0)
						{
							this_road = que_Pre[i];
						}
					}
					return step;
				}
				for (size_t i = 0; i < 4; i++)
				{
					string str_up = plus_one(str_cnw, i);
					int count_num = visited.count(str_up);
					if (visited.count(str_up) <= 0)
					{
						for (size_t i = 0; i < que_Pre.size(); i++)
						{
							if (que_Pre[i].back().compare(str_cnw)==0)
							{
								queue<string> que_tempUp = que_Pre[i];
								que_tempUp.push(str_up);
								que_Now.push_back(que_tempUp);
							}
						}
						visited.insert(str_up);
						q.push(str_up);
					}
					string str_down = down_one(str_cnw, i);
					if (visited.count(str_down) <= 0)
					{
						for (size_t i = 0; i < que_Pre.size(); i++)
						{
							if (que_Pre[i].back().compare(str_cnw)==0)
							{
								queue<string> que_tempDown = que_Pre[i];
								que_tempDown.push(str_down);
								que_Now.push_back(que_tempDown);
							}
						}
						visited.insert(str_down);
						q.push(str_down);
					}


				}
			}
			step++;//在哪里进行加入步数的计数比较关键
		}
		return -1;
	}

	queue<string> this_road;

};

int main() {
	vector<string> str_in = { "0201","0101","0102","1212","2002" };
	string str_target("0202");
	Solution s;
	int step = s.openLock(str_in, str_target);
	cout << step << endl;
	cout << "解锁步骤" << endl;

	while (!s.this_road.empty())
	{
	   cout << s.this_road.front() << "->";
	   s.this_road.pop();
	}
	cout << endl;
	system("pause");
	return 0;
}

本程序进行了改进,加入了关于每一个步的路径进行输出:

并没有进行优化,问题还是有的,记录路径的程序有冗余

如果步数更多的话,那么就会非常的冗余,影响运算速度。先提出优化思路-》比如经过一段时间将一些和目标太远的queue从容器里删除,进行优化。希望大家交流。

软件功能: 1-硬盘开机时须要输入安装时设置的密码(10位),密码不对开不了机,同时可选择使用USB盘做为开机密钥盘。 2-如果安装时插入USB盘,该盘将做为开机密钥,开机时显示:Shu Ru Mi Ma:+USB,不插该盘或插错盘,即使密码正确, 开机后自动关机。 3-如果安装时不插任何USB盘,将不检查密钥盘,开机时显示:Shu Ru Mi Ma:只要密码正确就可以开机。 4-安装时将改写硬盘MBR,故最好备份硬盘MBR到可以启动的USB盘,故障时用它启动执行其中恢复MBR,即可恢复。 5-安装本软件后正常关机,该硬盘的数据彻底得到保护,用光盘或其它启动盘启动也看不见此硬盘, 即使挂到其它电脑上也看不见。 6-做为USB开机密钥盘,不写入任何数据,USB原来的数据保留,只是不要重新格式化。 7-新建用户要重新安装一次,否则对新用户密钥盘无效,密码仍然有效,Wind7 Wind8不要开启UAC。 8-Windows8也不要开启[内置管理员账户的管理员批准模式],相当开启UAC。 9-本软件有注册窗口和机器码,但安装后可以无限制使用,不注册只在单日安装时有次数限制,使用中有未注册提示。 本软件在自己的联想笔记本和技嘉台式机上,WINXP,WIN7,WIN8系统下测试2年正常,其它机器环境下未做普遍试验, 为了安全最好在不重要的机器上试验,否则后果自负。 希望试用的朋友做好硬盘主引导区MBR备份及恢复工具,如果出现开不了机,用USB启动,恢复MBR就可以开机,重新安装后再卸载可以完全清除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值