C++ 算法——广搜BFS 2 代码实现(WZOI 720 硬币问题)

补充上上上……上篇文章广搜BFS

一、代码实现

在上上上……上篇文章广搜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;
}

点个支持一下谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值