poj1724 ROADS
题意:
N个城市,编号1到N。城市间有R条单向道路。
每条道路连接两个城市,有长度和过路费两个属性。
Bob只有K块钱,他想从城市1走到城市N。问最短共需要走多长的路。如果到不了N,输出-1
2<=N<=100
0<=K<=10000
1<=R<=10000
每条路的长度 L, 1 <= L <= 100
每条路的过路费T , 0 <= T <= 100
思路:
用d[i][j]表示从源点走到城市i并且花费为j的时候经过的最短距离。若在后续的搜索中,再次走到i时,如果总路费恰好为j,且此时的路径长度已经超过 d[i][j],则不必再走下去了。
1.深搜+剪枝
2.spfa+剪枝
实现:
1.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std; const int MAXN = ;
const int MAXK = ;
const int INF = 0x3f3f3f3f; struct node
{
int to, len, toll;
};
vector<node> G[MAXN + ];
int k, n, m, s, t, l, T, minLen = INF; bool vis[MAXN + ];
int d[MAXN + ][MAXK + ]; void dfs(int now, int rem, int len)
{
if (now == n)
{
minLen = min(minLen, len);
return;
}
for (int i = G[now].size() - ; i >= ; i--)
{
if (!vis[G[now][i].to] && rem >= G[now][i].toll)
{
if (d[G[now][i].to][rem - G[now][i].toll] <=
len + G[now][i].len || len + G[now][i].len >= minLen)
continue;
d[G[now][i].to][rem - G[now][i].toll] = len + G[now][i].len;
dfs(G[now][i].to, rem - G[now][i].toll, len + G[now][i].len);
vis[G[now][i].to] = false;
}
}
} int main()
{
cin >> k >> n >> m;
for (int i = ; i < m; i++)
{
cin >> s >> t >> l >> T;
node tmp;
tmp.to = t;
tmp.len = l;
tmp.toll = T;
if (s != t)
G[s].push_back(tmp);
}
memset(d, 0x3f, sizeof(d));
vis[] = true;
dfs(, k, );
if (minLen == INF)
puts("-1");
else
cout << minLen << endl;
return ;
}
2.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <functional>
using namespace std; const int MAXN = ;
const int MAXK = ;
const int INF = 0x3f3f3f3f; struct node
{
int to, len, toll;
};
vector<node> G[MAXN + ];
int k, n, m, s, t, l, T; struct co
{
int now, cost;
}; int d[MAXN + ][MAXK + ];
int in[MAXN + ][MAXK + ]; int spfa()
{
queue<co> q;
co start;
start.now = ;
start.cost = ;
q.push(start);
in[][] = true;
priority_queue<int, vector<int>, greater<int> > pq;
pq.push(INF);
while (!q.empty())
{
co tmp = q.front();
q.pop();
int now = tmp.now;
int cost = tmp.cost;
if (now == n)
{
pq.push(d[n][cost]);
}
in[now][cost] = false;
for (int i = ; i < G[now].size(); i++)
{
if (cost + G[now][i].toll <= k &&
d[now][cost] + G[now][i].len < d[G[now][i].to][cost + G[now][i].toll])
{
d[G[now][i].to][cost + G[now][i].toll] = d[now][cost] + G[now][i].len;
if (d[G[now][i].to][cost + G[now][i].toll] >= pq.top())
continue;
if (!in[G[now][i].to][cost + G[now][i].toll])
{
in[G[now][i].to][cost + G[now][i].toll] = true;
co son;
son.now = G[now][i].to;
son.cost = cost + G[tmp.now][i].toll;
q.push(son);
}
}
}
}
int minL = INF;
for (int i = ; i <= k; i++)
{
minL = min(minL, d[n][i]);
}
return minL;
} int main()
{
cin >> k >> n >> m;
for (int i = ; i < m; i++)
{
cin >> s >> t >> l >> T;
node tmp;
tmp.to = t;
tmp.len = l;
tmp.toll = T;
if (s != t)
G[s].push_back(tmp);
}
memset(d, 0x3f, sizeof(d));
for (int i = ; i <= k; i++)
{
d[][i] = ;
}
int minLen = spfa();
if (minLen >= INF)
puts("-1");
else
cout << minLen << endl;
return ;
}
最优性剪枝总结:
1. 从初始状态到当前状态的代价已经不小于目前找到的最优解,则剪枝。
2. 预测一下从当前状态到解的状态至少要花的代价W,如果W加上到达当前状态时已经花费的代价,必然不小于目前找到的最优解,则剪枝。
3. 如果到达某个状态A时,发现前面曾经也到达过A,且前面那次到达A所花代价更少,则剪枝。这要求记录到目前为止到达状态A时所能取得的最小代价。
poj1724 ROADS的更多相关文章
- 有限制的最短路spfa+优先队列
poj1724 ROADS Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10751 Accepted: 3952 De ...
- poj分类解题报告索引
图论 图论解题报告索引 DFS poj1321 - 棋盘问题 poj1416 - Shredding Company poj2676 - Sudoku poj2488 - A Knight's Jou ...
- POJ 1724 ROADS(使用邻接表和优先队列的BFS求解最短路问题)
题目链接: https://cn.vjudge.net/problem/POJ-1724 N cities named with numbers 1 ... N are connected with ...
- poj 1251 Jungle Roads (最小生成树)
poj 1251 Jungle Roads (最小生成树) Link: http://poj.org/problem?id=1251 Jungle Roads Time Limit: 1000 ...
- Jungle Roads[HDU1301]
Jungle Roads Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- POJ1947 Rebuilding Roads[树形背包]
Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 11495 Accepted: 5276 ...
- Constructing Roads——F
F. Constructing Roads There are N villages, which are numbered from 1 to N, and you should build som ...
- Constructing Roads In JGShining's Kingdom(HDU1025)(LCS序列的变行)
Constructing Roads In JGShining's Kingdom HDU1025 题目主要理解要用LCS进行求解! 并且一般的求法会超时!!要用二分!!! 最后蛋疼的是输出格式的注 ...
- 【CodeForces 567E】President and Roads(最短路)
Description Berland has n cities, the capital is located in city s, and the historic home town of th ...
随机推荐
- redis02---对于key的操作命令
Redis对于key的操作命令 del key1 key2 ... Keyn 作用: 删除1个或多个键 返回值: 不存在的key忽略掉,返回真正删除的key的数量 rename key newkey ...
- Codeforces Round #326 (Div. 2)
B. Duff in Love time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...
- 阶乘问题(大数阶乘)简单 n! (一个大数与一个小数相乘的算法 、一个大数与一个小数的除法算法 *【模板】 )
sdut oj 简单n! Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 给定一个数n(0 <= n <= 150), ...
- uptime详解,最通俗的说明了cpu平均负载
今天又个网友问uptime的三个平均负载值具体要怎么理解,发现要自己解释还真不知道怎么表达~~~~,下面到网上找了篇文章给大家分享: uptime命令,有两大用处,一个是看您的机器的运行时间,另一 ...
- [SDOI2016] 模式字符串 (BZOJ4598 & VIJOS1995)
首先直接点分+hash就可以做,每个点用hash判断是否为S重复若干次后的前缀或后缀,每个子树与之前的结果O(m)暴力合并.在子树大小<m时停止分治,则总复杂度为O(nlog(n/m)). 问题 ...
- C#使用SendMessage发送组合键
有时需要出发菜单功能,例如发送ALT + F打开应用程序的文件菜单,如何使用SendMessage实现呢? 使用用spy++截取的ALT+F的消息内容(如何使用spy++,请熟悉的高手指点下,我使用s ...
- HDFS之二:HDFS文件系统JavaAPI接口
HDFS是存取数据的分布式文件系统,HDFS文件操作常有两种方式,一种是命令行方式,即Hadoop提供了一套与Linux文件命令类似的命令行工具.HDFS操作之一:hdfs命令行操作 另一种是Java ...
- 让ie支持css3的一些htc文件
1. Dean Edwards的IE7.js (以及 IE8.js, IE9.js)这个玩意估计是试图让IE支持CSS3属性的鼻祖,还算蛮强大,就是性能开销较大,要解析很多文件脚本,给DOM添加大量的 ...
- SVN进行代码的托管
svn 使用的是集中服务器 就是只有一个服务器的意思 git 是分布式服务器 服务器: 存储客户端上传的源代码. 可以在Windows上通过安装 Visual SVN Sever . 客户端: 上 ...
- 数据库几种Top子句的使用方法
转自:https://blog.csdn.net/melody_susan/article/details/47011331