BFS/DFS解决隐式图/树问题

例题1

https://leetcode-cn.com/problems/perfect-squares/

描述

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.

Example 1:

Input: n = 12
Output: 3 
Explanation: 12 = 4 + 4 + 4.

Example 2:

Input: n = 13
Output: 2
Explanation: 13 = 4 + 9.

解析

class Solution {
public:
    unordered_set<int> sett;
    int numSquares(int n) {
        queue<int> q;
        q.push(0);
        int step=0;
        while(!q.empty()){
            step++;
            int cnt=q.size();
            while(cnt--){   //逐层入队
                int num=q.front();
                q.pop();
                for(int i=1;i*i<=n-num;i++){
                    int a=num+i*i;
                    if(a>n) break;
                    if(a==n) return step;
                    if(sett.count(a)==0){  //剪枝
                        q.push(a);  //将平方数的和入队以保存状态
                        sett.insert(a);
                    }                    
                }
            }            
        }
        return 0;
    }
};

例题2

https://www.luogu.com.cn/problem/P1032

题目描述

在这里插入图片描述在这里插入图片描述

解析

BFS:每次取出队首元素,对其按规则进行转换,将所有可能的转换结果都入队。可以通过将已经入队过的字符串加入到hashset中,入队时不用将已经入队过的字符串再入队(因为前面已经入队过了,再入队也不可能比前面一个更快地到达目标字符串),这就是一种“剪枝”。

这题有一个坑就是慎用size()-size(),具体见文章:这里

#include<iostream>
#include<string>
#include<vector>
#include<unordered_set>
#include<map>
#include<queue>
using namespace std;
unordered_set<string> sett;
vector<pair<string, string>> v;
queue<string> q;
int main() {
	//freopen("1.txt", "r", stdin);
	string a, b, ta, tb;
	cin >> a >> b;
	while (cin >> ta >> tb) {
		v.push_back({ ta,tb });
	}
	q.push(a);
	sett.insert(a);
	int step = 0;
	while (!q.empty() && step < 10) {
		int cnt = q.size();
		while (cnt--) {
			string now = q.front(); q.pop();
			if (now == b) {
				printf("%d", step);
				return 0;
			}
			for (auto it : v) {
				string s1 = it.first, s2 = it.second, next;
				if (now.size() < s1.size()) continue;  //注意这里
				for (int i = 0; i <= now.size() - s1.size(); i++) {
					auto pos = now.find(s1, i);
					if (pos != string::npos) {
						next = now;
						next.replace(pos, s1.size(), s2);
						if (!sett.count(next)) {
							q.push(next);
							sett.insert(next);
						}
					}
				}
			}
		}
		step++;
	}
	printf("NO ANSWER!");
	return 0;
}
小技巧:string.find()函数可以指定从哪个位置开始匹配,返回的仍然是在原始字符串中的位置。
发布了136 篇原创文章 · 获赞 12 · 访问量 6089

猜你喜欢

转载自blog.csdn.net/weixin_43590232/article/details/104735102
今日推荐