ACM记忆化DFS与基于优先队列的BFS

news2025/3/15 0:53:58

基本概念--记忆化DFS

使用数组保存已经算出来的值,在后续的计算中减少大量的重复计算,提高效率。(用于dp不方便,但是搜索方便的情况,可以提升效率。)

eg. 记忆化dfs求解斐波那契数列

int dfs(int n)
{
	if(fib[n]) return n;
	if(n==1 || n==2) fib[n] = 1;
	else fib[n] = (dfs(n-1)+dfs(n-2)) % 1000000007;
	return fib[n];
}

 

经典例题

猫和老鼠

        :将每一个位置所能得到的最优解都保存在一个二维数组中,每次调用dfs函数时都先判断这个位置的最优解是否曾经已经求出来了,假如求出来了直接返回就行了。

#include <cstdio>
#include <cstring>
using namespace std;

int n, k, init[101][101], ans[101][101];    //init保存每个网格最初奶酪的值,ans保存从当前这个坐标出发能够得到的最优解
int moves[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int dfs(int x, int y);
int max(int x, int y) { return x > y ? x : y; }
bool ok(int x, int y) { return x <= n && y <= n && x > 0 && y > 0; }    //判断是否越界

int main()
{
	while(scanf("%d%d", &n, &k), n != -1 && k!= -1)
	{
		memset(ans, 0, sizeof(ans));
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= n; j++)
				scanf("%d", &init[i][j]);
		printf("%d\n", dfs(1, 1));
	}
	return 0;
}

int dfs(int x, int y)    //返回从(x,y)出发得到的最优解
{
	int tempMax = 0;
	if(ans[x][y]) return ans[x][y];
	for(int i = 0; i < 4; i++)
		for(int j = 1; j <= k; j++)
		{
			int xx = x + j*moves[i][0];
			int yy = y + j*moves[i][1];
			if(ok(xx, yy) && init[xx][yy] > init[x][y])
				tempMax = max(tempMax, dfs(xx, yy));
		}
	ans[x][y] = init[x][y] + tempMax;
	return ans[x][y];
}

How many ways

        :假如知道了从蓝色位置走到终点的方案数,那么从左上角(起点)走到终点的方案数也就知道了(所有蓝色方块方案数的和)。

#include <cstdio>
#include <cstring>
using namespace std;

int n, m, t, map[101][101], ans[101][101];
int ok(int x, int y){ return x <= n && y <= m && x > 0 && y > 0; }
int dfs(int, int);

int main()
{
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d%d", &n, &m);
		memset(ans, -1, sizeof(ans));
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= m; j++)
				scanf("%d", &map[i][j]);
		ans[n][m] = 1;
		printf("%d\n", dfs(1, 1));
	}
	return 0;
}

int dfs(int x, int y)
{
	if(ans[x][y] > -1) return ans[x][y];
	ans[x][y] = 0;
	for(int i = 0; i <= map[x][y]; i++)
		for(int j = 0; j <= map[x][y]-i; j++)
			if(ok(x+i, y+j))
				ans[x][y] = (dfs(x+i, y+j)+ans[x][y]) % 10000;
	return ans[x][y];
}

 

基本概念--基于优先队列的BFS

优先队列(priority_queue):

  1. 在队尾加入元素
  2. 在队头删除元素
  3. 每次取出的时具有最高优先权的元素

基本用法

创建队列对象:priority_queue<元素类型> 队列名;

队列添加元素:队列名.push(元素名);

去掉最优元素:队列名.pop();

判断是否为空:队列名.empty();

返回队列大小:队列名.size();

访问最优元素:队列名.top();

假如需要对结构体数组定义“优先权”,那么就要重载运算符

eg. 保存三个整数的结构体,从前往后依次比较三个整数,从小往大排。

struct T
{
    int x, y, z;
    friend bool operater < (T t1, T t2)
    {
        if(t1.x != t2.x) return t1.x > t2.x;
        if(t1.y != t2.y) return t1.y > t2.y;
        return t1.z > t2.z;
    }
};

 

经典例题

拯救丁爸

        :前来拯救的学生有多个时,可以反向思考(丁爸找学生的位置)。

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int n, m, ans;
char map[201][201]; 
int mintime[201][201];
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};

struct state {
    int x, y, ti; 
    friend bool operator < (state s1,state s2)
    {
        return s2.ti < s1.ti;
    }
};

state be;

bool in(int x, int y) { return x >= 1 && y >= 1 && x <= n && y <= m && map[x][y] != '#'; }

int bfs() 
{
    priority_queue<state> q;
    q.push(be);
    state cur, next;
    while (!q.empty()) 
	{
        cur = q.top();
        mintime[cur.x][cur.y] = 1;
        if (map[cur.x][cur.y] == 'r') return cur.ti;
        q.pop();
        for (int i = 0; i < 4; i++) 
		{
            next.x = cur.x + dir[i][0];
            next.y = cur.y + dir[i][1];
            if (in(next.x, next.y)) 
			{
                next.ti = cur.ti+1;
                if (map[next.x][next.y] == 'x') next.ti++;
                if(!mintime[next.x][next.y])
                {
                    q.push(next);
                    mintime[next.x][next.y] = 1;
                }
            }
        }
    }
    return 0;
}

int main() 
{
    while (cin >> n >> m) 
	{
        ans = 0; 
		memset(mintime, 0, sizeof(mintime));
        for (int i = 1; i <= n; i++) 
		{
            for (int j = 1; j <= m; j++) 
			{
                cin >> map[i][j];
                if (map[i][j] == 'a') 
				{
                    be.x = i; 
					be.y = j;
                    be.ti = 0;
                }
            }
        }
        int t = bfs();
        if(t) cout << t << endl;
        else cout << "Poor Dingba has to stay in the prison all his life." << endl;
    }
}

哈夫曼编码

概念

  • 路径:由一个节点到另一个节点间的分支构成
  • 路径长度:路径上经过的分支数量
  • 树的路径长度:从树根到每一节点的路径长度之和
  • 带权路径长度:节点到根的路径长度与节点上权重的乘积
  • 树的带权路径长度:树中所有叶子节点的带权路径长度之和,WPL=\sum w_i\cdot l_i(Weighted Path Length)
  • 哈夫曼树:带权路径长度最小的树

作用:在发送报文时可以构造最少的01序列来表示所有字母。

特点:每一个码都不是另一个码的前缀,称为前缀码。(所以发电报的时候才不会产生歧义。)

:每次在优先队列中找两个最小的数,把它们的和插入优先队列。如此往复就可以得到一个哈夫曼树。

#include <iostream>
#include <string>
#include <cstring>
#include <queue>
using namespace std;

string str;
int num[27];
int bfs();

int main()
{
	while(cin >> str, str != "END")
	{
		memset(num, 0, sizeof(num));
		int len = str.size();
		for(int i = 0; i < len; i++)
		{
			if(str[i] == '_') num[26]++;
			else num[str[i]-'A']++;
		}
		int res = bfs();
		printf("%d %d %.1f\n", len*8, res, len*8*1.0/res);
	}
	return 0;
}

int bfs()
{
	int a, b, sum=0;
	priority_queue<int, vector<int>, greater<int> > Q;
	for(int i = 0; i <= 26; i++)
		if(num[i]) Q.push(num[i]);
	if(Q.size() == 1) sum = Q.top();
	while(Q.size() > 1)
	{
		a = Q.top();
		Q.pop();
		b = Q.top();
		Q.pop();
		sum += a + b;
		Q.push(a+b);
	}
	return sum;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1519032.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常州不大创造神话!常州股票开户佣金最低多少!股票开户佣金最低是多少?

股票操作准则是指在进行股票交易时遵循的一些基本原则和规范。以下是一些常见的股票操作准则&#xff1a; 量力而行&#xff1a;要根据自己的经济实力和风险承受能力选择适合自己的股票操作方式&#xff0c;不要盲目追求高回报而忽视风险。 分散投资&#xff1a;将资金分散投资…

力扣46. 全排列

Problem: 46. 全排列 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 回溯可以理解为是在对一个多叉树的操作 1.回溯结束条件&#xff1a;当决策路径的长度等于nums数组的长度时&#xff0c;将当前的结果添加到二维结果集res中&#xff1b; 2.每一次决策的选择处…

市场广泛看好的LaunchPad 平台 PenPad,有望在牛市胜出?

随着 ETF 效应下&#xff0c;推动比特币不断突破前高&#xff0c;这也进一步推动市场走向牛市。事实上&#xff0c;在每一轮牛市行情中&#xff0c;都会涌现出大量的新项目&#xff0c;并伴随大量的资产面向市场&#xff0c;而如何帮助这些资产、项目实现更好的启动变得尤为关键…

【深度学习笔记】10_10 束搜索beam-search

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 10.10 束搜索 上一节介绍了如何训练输入和输出均为不定长序列的编码器—解码器。本节我们介绍如何使用编码器—解码器来预测不定长的序…

记一次Spring事务失效的发现与解决过程

一、事情起因是这样的 首先&#xff0c;我们是使用Spring mybatis 进行开发。 某功能在测试环境看到报错日志&#xff0c; 但是数据库里面的数据发生了变化&#xff0c;没有回滚。 执行数据库update 操作的方法上明确有 Transactional(rollbackFor Exception.class)的注解。…

使用nuclei扩充自己的武器库-nuclei3 sdk开发指南

一、nuclei是什么 Nuclei 是一个快速、灵活、可扩展的开源漏洞扫描工具&#xff0c;用于发现 Web 应用程序中的安全问题。它允许安全研究人员和渗透测试人员轻松地定义和执行定制的漏洞扫描任务。 Nuclei 使用模板来定义漏洞扫描任务。这些模板是基于 YAML 格式的&#xff0c…

什么是MVC三层结构

1.MVC&#xff08;三层结构&#xff09; MVC&#xff08;Model-View-Controller&#xff09;是一种常见的软件设计模式&#xff0c;用于将应用程序的逻辑和界面分离成三个不同的组件。每个组件负责特定的任务&#xff0c;从而提高代码的可维护性和可扩展性。 以前的模式。 遇到…

kettle 9.4和Pentoho 9.4下载及安装方法简介

kettle 9.4和Pentoho 9.4下载及安装方法简介 下载地址&#xff1a; https://sourceforge.net/projects/pentaho/files/ 下载步骤&#xff1a; #------------- 一、点击选项卡&#xff1a;summary/ 二、点击第一行链接 https://www.hitachivantara.com/en-us/products/pentaho…

姿态旋转的哥氏定理以及速度微分的推导

姿态旋转中涉及到坐标系的转换&#xff0c;在有相对旋转的两个坐标系中观察一个向量的变化&#xff0c;用到了哥氏定理。 例如在i系中观察e系下的运动&#xff0c;则 哥氏定理的公式 wie是e相对于i的角运动 注意符号i在前e在后。 wie是e相对于i的角运动 注意符号i在前e在…

WRF模型教程(ububtu系统)-WPS(WRF Pre-Processing System)概述

一、WPS简介 WRF 预处理系统 (WRF Pre-Processing System&#xff0c;WPS) &#xff0c;集成了基于Fortran和C编写的程序&#xff0c;这些程序主要用于处理输入到real.exe的数据。WPS主要有三个程序和一些辅助程序。 二、各程序介绍 主要的程序为geogrid.exe、ungrib.exe、met…

一篇文章带你了解低保真与高保真原型图区别

在原型设计中&#xff0c;低保真原型和高保真原型的区别主要体现在细节和功能上。那么我们在设计原型的时候是用低保真原型还是高保真原型呢&#xff1f;两者最好的使用场景是什么&#xff1f;对此&#xff0c;即时设计做了相应的分析。让我们来看看&#xff01; 1、低保真原型…

[蓝桥杯]-最大的通过数-CPP-二分查找、前缀和

目录 一、题目描述&#xff1a; 二、整体思路&#xff1a; 三、代码&#xff1a; 一、题目描述&#xff1a; 二、整体思路&#xff1a; 首先要知道不是他们同时选择序号一样的关卡通关&#xff0c;而是两人同时进行两个入口闯关。就是说两条通道存在相同关卡编号的的关卡被通…

3冠达成!原知因制药荣获2024年度JMR消费者评选三大No.1

近日&#xff0c;日本调查机构&#xff08;JMR&#xff09;公布了2024年度公众对品牌形象的调查结果&#xff0c;除了人们熟知的资生堂、CPB、POLA、小林制药、DHC等品牌依然获得不错的口碑外&#xff0c;日本高端健康品牌原知因制药凭借优秀的产品实力及良好的社会口碑&#x…

Python新手必学:输入输出全攻略

初学Python编程时&#xff0c;其中一个最基础、也是最重要的部分就是如何处理输入和输出。无论是简单的用户输入&#xff0c;还是程序输出结果&#xff0c;都很重要。现在&#xff0c;我们将一起学习Python输入输出的各种技巧和方法&#xff0c;让你在编写代码时得心应手。 目…

HTML5:七天学会基础动画网页11

CSS3动画 CSS3过渡的基本用法: CSS3过渡是元素从一种样式逐渐改变为另一种样式的效果。 过渡属性-transition 值与说明 transition-property 必需&#xff0c;指定CSS属性的name&#xff0c;transition效果即哪个属性发生过渡。 transition-duration 必需&#xff0c;t…

YOLOv9改进策略:注意力机制 |通道注意力和空间注意力CBAM | GAM超越CBAM,不计成本提高精度

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文改进内容&#xff1a;通道注意力和空间注意力CBAM&#xff0c;全新注意力GAM&#xff1a;超越CBAM&#xff0c;不计成本提高精度 改进结构图如下&#xff1a; YOLOv9魔术师专栏 ☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️…

LeetCode2115. 从给定原材料中找到所有可以做出的菜

拓扑排序 题面 题目链接&#xff1a;2115. 从给定原材料中找到所有可以做出的菜 - 力扣&#xff08;LeetCode&#xff09; 你有 n 道不同菜的信息。给你一个字符串数组 recipes 和一个二维字符串数组 ingredients 。第 i 道菜的名字为 recipes[i] &#xff0c;如果你有它 所有…

openstack(T)启动实例状态为错误,如何解决

---基本服务得是正常的 ---1.在web界面看是什么错误 点击你的实例名称&#xff0c;在概况里面去查看 当时我的error &#xff1a;编码500 消息 No valid host was found. 错误原因 1&#xff1a;资源不足 2&#xff1a;未开启虚拟机cpu虚拟化 解决&#xff1a; 1.资源不…

Element-Plus: Select组件实现滚动分页加载

Element-Plus的select组件并没有自带滚动分页加载的功能&#xff0c;其虽然提供了自定义下拉菜单的底部的方式可以自定义上一页及下一页操作按钮的方式进行分页加载切换&#xff1a; 但如果不想通过点击分页按钮的方式&#xff0c;利用滚动触底进行下一页加载的话&#xff0c;…

Arrays对象数组排序 --java学习笔记

假设有四个学生对象&#xff1a; name:"小明",height:168.8,age:22 name:"小红",height:178.5,age:20 name:"小智",height:160.1,age:21 name:"小白",height:230.6,age:22 现在需要按身高对他们进行排序 对象进行排序&#xff0c;默…