[POJ]2449. Remmarguts' Date
2015-10-12 14:33
357 查看
这道题是求一个有向图上的第k短路。这时,可以采用A*搜索,也就是启发式搜索的办法。所谓启发式搜索,是在搜索的时候设置一个启发式函数,以此来确定搜索的顺序,,从而减少无用功。
本题中,启发函数为f(x) = distance_traveled(x) + distance_remaining(x). 前者为搜索到x点时已经走过的路程,后者为到终点还剩的路程。可以在A*搜索之前把后者先全部预处理出来以节省时间。在A*搜索时可以用C++的priority_queue来做,注意这个优先队列是把大的数据放在前面的,所以自己在结构体中重载优先级的时候要注意把f(x)小的定义成大的。
P. S. 时隔两年多再写这个博客,有点感慨啊。。。
本题中,启发函数为f(x) = distance_traveled(x) + distance_remaining(x). 前者为搜索到x点时已经走过的路程,后者为到终点还剩的路程。可以在A*搜索之前把后者先全部预处理出来以节省时间。在A*搜索时可以用C++的priority_queue来做,注意这个优先队列是把大的数据放在前面的,所以自己在结构体中重载优先级的时候要注意把f(x)小的定义成大的。
P. S. 时隔两年多再写这个博客,有点感慨啊。。。
#include <cstdio> #include <queue> using namespace std; struct Edge { int dt, c, next; }; const int INF = 1000000; int n, m, edgenum1, edgenum2, s, t, k, dis[2000], vis[2000], first1[2000], first2[2000]; Edge edge1[110000], edge2[110000]; struct a_star { int v, len; bool operator < (const a_star &a) const { return len + dis[v] > a.len + dis[a.v]; } }; void init() { edgenum1 = edgenum2 = 0; for (int i = 1; i <= n; i++) first1[i] = first2[i] = 0; } void add_edge1(int u, int v, int c) { edgenum1++; edge1[edgenum1].next = first1[u]; edge1[edgenum1].dt = v; edge1[edgenum1].c = c; first1[u] = edgenum1; } void add_edge2(int u, int v, int c) { edgenum2++; edge2[edgenum2].next = first2[u]; edge2[edgenum2].dt = v; edge2[edgenum2].c = c; first2[u] = edgenum1; } void dijk(int u) { int i, j, tmp; for (i = 1; i <= n; i++) { vis[i] = 0; dis[i] = INF; } dis[u] = 0; for (i = 1; i <= n; i++) { int mini, minc = INF; for (j = 1; j <= n; j++) if (!vis[j] && dis[j] < minc) { minc = dis[j]; mini = j; } vis[mini] = 1; tmp = first2[mini]; while (tmp) { int c = edge2[tmp].c, v = edge2[tmp].dt; tmp = edge2[tmp].next; if (vis[j] || dis[v] <= dis[mini] + c) continue; dis[v] = dis[mini] + c; } } } int solve() { if (s == t) k++; if (vis[s] == 0) return -1; for (int i = 1; i <= n; i++) vis[i] = 0; a_star n1; priority_queue <a_star> q; n1.v = s; n1.len = 0; q.push(n1); while (!q.empty()) { a_star head = q.top(); q.pop(); vis[head.v]++; if (vis[t] == k) return head.len; if (vis[head.v] > k) continue; int tmp = first1[head.v]; while (tmp) { a_star n2; n2.v = edge1[tmp].dt; n2.len = edge1[tmp].c + head.len; tmp = edge1[tmp].next; q.push(n2); } } return -1; } int main() { int u, v, c; scanf("%d%d", &n, &m); init(); for (int i = 1; i <= m; i++) { scanf("%d%d%d", &u, &v, &c); add_edge1(u, v, c); add_edge2(v, u, c); } scanf("%d%d%d", &s, &t, &k); dijk(t); printf("%d\n", solve()); return 0; }
相关文章推荐
- Apriori算法(C#)
- Web classPath
- 模拟Spring的简单实现
- 如何对jmeter设置IP欺骗
- 结合固件库探讨STM32读写FLASH步骤、HardFault问题
- android TextView文字加粗
- 零成本实现接口自动化测试 – Java+TestNG 测试Restful service
- 如何下载PHP开发文档
- db2实例、数据库、表空间
- 如何创建圆角 UITextField 与内阴影
- Github上传文件--未完成
- dhcpd 源码分析
- [Android Studio 权威教程]多渠道打包和一键完成(全部产品)打包并签名
- Maven实战 第2章 Maven的安装和配置gai
- Boost.Asio性能测试(★firecat推荐,红色字体是本人的标识★)
- Android图形子系统详解
- JSP实现从mysql读取数据并实现分页功能
- 将Eclipse中Web项目自动部署到Tomcat
- PHP获取MP3时长类
- 为控件添加动画效果(安卓)