\(\text{A*}\)

一种启发式搜索

和暴搜的差别是多了一个估价函数,每次取出一个估算最优的状态以期更高效完成任务

重点在于估价函数 \(\text{h*(n)}\) 的设计,若实际代价为 \(\text{h(n)}\),则

若 \(\text{h*(n)=h(n)}\),设计得非常好

若 \(\text{h*(n)<h(n)}\),跑得更快,只是可能搜不出来正确答案

若 \(\text{h*(n)>h(n)}\),慢是慢些,但正确性还有保证

例如 \(k\) 短路

暴搜的话就是找出所有路径,取第 \(k\) 短

但实际上若精准预估当前状态到终止状态的代价,每次取出最小代价状态,

那么 \(k\) 次到达终止状态后,前 \(k\) 短路就已经被搜出来了

显然,估价函数就定为当前状态到终止状态的最短路

这个可以反向建图 \(\text{dijkstra}\) 预处理

\(\text{sample}\)

P2483 【模板】k 短路 / [SDOI2010] 魔法猪学院

$\text{Code}$
#include <cstdio>
#include <queue>
#define RE register
#define IN inline
using namespace std; const int N = 5005, M = 2e5 + 5, INF = 1e18;
int n, m, cnt[N];
double e; struct node{
int id; double f, v;
bool operator < (const node &c) const{return f > c.f;}
};
priority_queue<node> Q; struct graph{
struct edge{int to, nxt; double w;}e[M];
int tot, h[N], vis[N]; double dis[N];
IN void add(int u, int v, double w){e[++tot] = edge{v, h[u], w}, h[u] = tot;}
IN void getdis()
{
for(RE int i = 1; i < n; i++) dis[i] = INF, vis[i] = 0;
vis[n] = 0, Q.push(node{n, 0});
while (!Q.empty())
{
node x = Q.top(); Q.pop();
if (vis[x.id]) continue;
vis[x.id] = 1;
for(RE int i = h[x.id]; i; i = e[i].nxt)
{
int v = e[i].to;
if (dis[v] > dis[x.id] + e[i].w)
Q.push(node{v, dis[v] = dis[x.id] + e[i].w});
}
}
}
}e1, e2; int main()
{
scanf("%d%d%lf", &n, &m, &e);
int u, v; double w;
for(RE int i = 1; i <= m; i++) scanf("%d%d%lf", &u, &v, &w), e1.add(u, v, w), e2.add(v, u, w);
e2.getdis(), Q.push(node{1, 0});
int k = (int)e / e2.dis[1], ans = 0;
while (!Q.empty())
{
node x = Q.top(); Q.pop();
++cnt[x.id];
if (x.id == n)
{
e -= x.v;
if (e <= 0){printf("%d\n", ans); return 0;}
++ans;
}
for(RE int i = e1.h[x.id]; i; i = e1.e[i].nxt)
{
int v = e1.e[i].to;
if (cnt[v] < k && x.v + e1.e[i].w + e2.dis[v] <= e)
Q.push(node{v, x.v + e1.e[i].w + e2.dis[v], x.v + e1.e[i].w});
}
}
printf("%d\n", ans);
}

P2901 [USACO08MAR]Cow Jogging G

$\text{Code}$
#include <cstdio>
#include <queue>
#define RE register
#define IN inline
typedef long long LL;
using namespace std; const int N = 1005, M = 2e5 + 5, INF = 1e9;
int n, m, k, cnt[N]; struct node{
int id; LL f, v;
bool operator < (const node &c) const{return f > c.f;}
};
priority_queue<node> Q; struct graph{
struct edge{int to, nxt, w;}e[M];
int tot, h[N], vis[N]; LL dis[N];
IN void add(int u, int v, int w){e[++tot] = edge{v, h[u], w}, h[u] = tot;}
IN void getdis()
{
for(RE int i = 2; i <= n; i++) dis[i] = INF, vis[i] = 0;
vis[1] = 0, Q.push(node{1, 0});
while (!Q.empty())
{
node x = Q.top(); Q.pop();
if (vis[x.id]) continue;
vis[x.id] = 1;
for(RE int i = h[x.id]; i; i = e[i].nxt)
{
int v = e[i].to;
if (dis[v] > dis[x.id] + e[i].w)
Q.push(node{v, dis[v] = dis[x.id] + e[i].w});
}
}
}
}e1, e2; int main()
{
scanf("%d%d%d", &n, &m, &k);
for(RE int i = 1, u, v, w; i <= m; i++) scanf("%d%d%d", &u, &v, &w), e1.add(u, v, w), e2.add(v, u, w);
e2.getdis(), Q.push(node{n, 0});
int sum = 0;
while (!Q.empty())
{
node x = Q.top(); Q.pop();
++cnt[x.id];
if (x.id == 1)
{
printf("%d\n", x.v), ++sum;
if (sum == k) return 0;
}
for(RE int i = e1.h[x.id]; i; i = e1.e[i].nxt)
{
int v = e1.e[i].to;
if (cnt[v] < k)
Q.push(node{v, x.v + e1.e[i].w + e2.dis[v], x.v + e1.e[i].w});
}
}
for(RE int i = sum; i < k; i++) printf("-1\n");
}

最新文章

  1. nginx配置杂记
  2. ios 缺少合规证明
  3. HttpURLConnection 直接发送soap消息调用webservice
  4. 基于mjpg_streamer视频服务器移植【转】
  5. 菜鸟-手把手教你把Acegi应用到实际项目中(2)
  6. hdu 4657 Find Permutation
  7. android 小米手机连接到电脑adb无法识别 解决方案
  8. html良好结构-之豆瓣风格
  9. Coursera获取中文字幕(如果有的话)
  10. 设置PlaceHolder的颜色
  11. Linux中切换用户变成-bash4.1-$的解决方法【转】
  12. springmvc的jdbcTemplate 插入 返回主键
  13. bootstrap - btn
  14. phpstorm 怎么实现分屏展示
  15. RabbitMQ 发布订阅持久化
  16. centos 6.5 ruby环境安装
  17. (原)kenel开机logo的制作
  18. 测试工具之badboy
  19. quartz.net 的配置文件资料
  20. Oracle EBS AR 更新客户账户层

热门文章

  1. 编译安装oh-my-zsh
  2. 记一次windows10电脑连上wifi无法上网的解决问题
  3. 产生10个1-20以内的随机数,要求不能重复(集合)Java
  4. PyTorch复现VGG学习笔记
  5. 动态更改Spring定时任务Cron表达式的优雅方案
  6. k3s安装kubernetes环境
  7. JUC源码学习笔记5——1.5w字和你一起刨析线程池ThreadPoolExecutor源码,全网最细doge
  8. angular在服务中调用组件的某个方法,并传参给组件,(反向调用),变量改变后,强制更新视图
  9. Z-Blog后台getshell
  10. LeetCode_387. 字符串中的第一个唯一字符