1025 - K短路(A*算法) - 魔法猪学院(SDOI 2010)

2023-12-01 11:40

本文主要是介绍1025 - K短路(A*算法) - 魔法猪学院(SDOI 2010),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

魔法猪学院(magic)
描述

iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练。经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的;元素与元素之间可以互相转换;能量守恒……。
能量守恒……iPig 今天就在进行一个麻烦的测验。iPig 在之前的学习中已经知道了很多种元素,并学会了可以转化这些元素的魔法,每种魔法需要消耗 iPig 一定的能量。作为 PKU 的顶尖学猪,让 iPig 用最少的能量完成从一种元素转换到另一种元素……等等,iPig 的魔法导猪可没这么笨!这一次,他给 iPig 带来了很多 1 号元素的样本,要求 iPig 使用学习过的魔法将它们一个个转化为 N 号元素,为了增加难度,要求每份样本的转换过程都不相同。这个看似困难的任务实际上对 iPig 并没有挑战性,因为,他有坚实的后盾……现在的你呀!
注意,两个元素之间的转化可能有多种魔法,转化是单向的。转化的过程中,可以转化到一个元素(包括开始元素)多次,但是一但转化到目标元素,则一份样本的转化过程结束。iPig 的总能量是有限的,所以最多能够转换的样本数一定是一个有限数。具体请参看样例。

输入

第一行三个数 N、M、E 表示iPig知道的元素个数(元素从 1 到 N 编号)、iPig已经学会的魔法个数和iPig的总能量。
后跟 M 行每行三个数 si、ti、ei 表示 iPig 知道一种魔法,消耗 ei 的能量将元素 si 变换到元素 ti

输出

一行一个数,表示最多可以完成的方式数。输入数据保证至少可以完成一种方式。

样例输入

4 6 14.9
1 2 1.5
2 1 1.5
1 3 3
2 3 1.5
3 4 1.5
1 4 1.5

样例输出

3

样例解释

有意义的转换方式共4种:
1->4,消耗能量 1.5
1->2->1->4,消耗能量 4.5
1->3->4,消耗能量 4.5
1->2->3->4,消耗能量 4.5
显然最多只能完成其中的3种转换方式(选第一种方式,后三种方式仍选两个),即最多可以转换3份样本。
如果将 E=14.9 改为 E=15,则可以完成以上全部方式,答案变为 4。

数据规模

占总分不小于 10% 的数据满足 N <= 6,M<=15。
占总分不小于 20% 的数据满足 N <= 100,M<=300,E<=100且E和所有的ei均为整数(可以直接作为整型数字读入)。
所有数据满足 2 <= N <= 5000,1 <= M <= 200000,1<=E<=107,1<=ei<=E,E和所有的ei为实数。


分析

第一次接触 A* 算法,感觉这玩意儿好妙好妙
其实也不是什么特别难懂的知识,就是类似贪心的Bfs
一般的深搜,就是乱搞,就很容易各种超时
而 A* 是怎么优化的呢?

一般的 BFS扩展最小耗费的点。A*算法在另一方面,扩展最有希望的点(估价函数返回值最优)。 状态被保存在一个优先队列中,按照Cost价值排列。每一次,程序处理最低优先的点,且把它的孩子按照适当顺序处理。
对于一个可容许的估价函数,第一个找到的状态保证是最优的。

说的再简单一点,就是相当于给我们的 Bfs 一个导向,指引着他往我们需要的最优解前进,中途会少很多不必要的深搜,这复杂度就直线下降

那么具体的什么是估价函数呢?
就是以任意状态为输入,计算出从该状态到目标状态所需代价的估计值,这个函数的设计必须要满足的一个条件就是估价函数的估值不能大于未来的实际代价

对于这道题
在这里插入图片描述

这个f[]就是估价函数,而dis+len(x,y)就是真实值

#include<bits/stdc++.h>
#define re register
#define N 5009
#define M 400009
#define in read()
using namespace std;
inline int read(){char ch;int f=1,res=0;while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+ch-'0';ch=getchar();}return f==1?res:-res;
}
int n,m,S,T,ans;
double tot,dis[N];
struct node{int u;double cost;};
bool operator <(const node &a,const node &b){return dis[a.u]+a.cost>dis[b.u]+b.cost;
}
int nxt[M],to[M],head[N],cnt=0;
double w[M];
void add(int x,int y,double z){nxt[++cnt]=head[x];head[x]=cnt;to[cnt]=y;w[cnt]=z;
}
int Nxt[M],To[M],Head[N],Cnt=0;
double W[M];
void conadd(int x,int y,double z){Nxt[++Cnt]=Head[x];Head[x]=Cnt;To[Cnt]=y;W[Cnt]=z;
}
bool vis[N];
void spfa(){memset(dis,127,sizeof(dis));queue<int > q;q.push(S);dis[S]=0;while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int e=Head[u];e;e=Nxt[e]){int v=To[e];if(dis[v]>dis[u]+W[e]){dis[v]=dis[u]+W[e];if(!vis[v]) q.push(v),vis[v]=1;}}}
}
priority_queue<node> que;
void Astar(){que.push((node){S,0});while(!que.empty()){node now=que.top();que.pop();if(now.u==T){tot-=now.cost;if(tot<0) return;ans++;continue;}for(int e=head[now.u];e;e=nxt[e]){int v=to[e];que.push((node){v,now.cost+w[e]});}}
}
int main(){n=in;m=in;scanf("%lf",&tot);int u,v,i,j,k;double len;for(i=1;i<=m;++i){u=in;v=in;scanf("%lf",&len);conadd(v,u,len);add(u,v,len);}S=n;T=1;spfa();//处理出估价函数disans=0; S=1;T=n;Astar();cout<<ans;return 0;
}

这篇关于1025 - K短路(A*算法) - 魔法猪学院(SDOI 2010)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/441022

相关文章

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

Rust中的Drop特性之解读自动化资源清理的魔法

《Rust中的Drop特性之解读自动化资源清理的魔法》Rust通过Drop特性实现了自动清理机制,确保资源在对象超出作用域时自动释放,避免了手动管理资源时可能出现的内存泄漏或双重释放问题,智能指针如B... 目录自动清理机制:Rust 的析构函数提前释放资源:std::mem::drop android的妙

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个