一、代码实现
在上上上……上篇文章广搜BFS,我们知道了广搜的思路,今天来说它的代码如何实现。
首先,第一需要用到的,就是队列(见 C++ 队列(WZOI 846 模拟队列)),把搜到的结果push进去。举个例子,假如有一个X,每次可以 +1, -1, *2,求它到Y的最少操作次数(和白云小区的奶牛有亿点像)就可以把X先push进去,再每次检查队首,如果等于Y就得到答案,不等于就将它+1,-1,*2的答案全部入队首,再将它pop掉……那到答案的步数怎么算呢?可以定义一个结构体:
struct data{
int num;
int step;
};
其中step是X到num的步数。再把队列的定义改成
queue <data> q;
就可以在得到答案的同时得到步数啦!
但是你真的以为这么简单吗?如果不优化绝对超时。
如果说碰到一个队首等于5,即q.front().num = 5;,Y = 17,q.front().num != Y,于是q.push(data{q.front().num + 1, q.front().step + 1});下次碰到这个push进去的数6,不等于17,于是你又q.push(data{q.front().num - 1, q.front().step + 1});,又push进5……这样无限循环绝对超时或答案错误。所以可以建立一个vis数组记录当前数(q.front().num)有没有被访问过,没访问过就先检查等不等于Y,再把vis[q.front().num] = 1,表示已被访问过,下次push元素的时候就可以避免再访问到这个数。
二、硬币问题
这里来 扯 一道 虽然题目标签是动态规划,但 可以用BFS解决的题。
硬币问题
题目描述:
今有无限的面值为1,5,11元的硬币。
给定n,问:至少用多少枚硬币,可以恰好凑出n元?
输入格式:
一个整数n。
输出格式:
一个整数,表现最少的硬币数。
样例输入:
15
样例输出:
3
提示:
数据范围:1≤n≤10000
时间限制: 1000ms
空间限制: 256MB
附上AC代码:
#include<bits/stdc++.h>
using namespace std;
struct data{
int num;
int step;
};
int n;
queue<data>q;
int vis[10010];
int main(){
cin >> n;
q.push(data{n,0});
while(!q.empty()){
data head = q.front();q.pop();
data x = head;
if(x.num == 0){
cout << x.step << '\n';
return 0;
}
if(x.num - 11 >= 0 && !vis[x.num - 11]){
q.push(data{x.num - 11, x.step + 1});
vis[x.num - 11] = 1;
}
if(x.num - 5 >= 0 && !vis[x.num - 5]){
q.push(data{x.num - 5, x.step + 1});
vis[x.num - 5] = 1;
}
else if(x.num - 1 >= 0 && !vis[x.num - 1]){
q.push(data{x.num - 1, x.step + 1});
vis[x.num - 1] = 1;
}
}
return 0;
}
点个赞,支持一下谢谢!