poj2686 状压dp
2016-07-21 20:45
302 查看
题目链接:点击打开链接
题意:
有个人要从一个城市 a 到城市 b;
其中他有 n 张马车票;
每张马车票有一个速度 t[i];
地图上有 p 条路;
每条路是双向的,并且有个距离 d[i];
他每走一条路就要花一张马车票;
一张马车票只能用于一条路;
求他所要花的最短时间;
理解:
dp 咯。。。
推不出来啊,状态压缩dp;
一看递推式含义就能明白很多了;
dp[i][j] 表示用 i 张票到达 j 城市所花的最短时间;
递推式:dp[i | (1 << k)][e] = min(dp[i | (1 << k)][e], dp[i][j] + d[j][e] / t[k]);
即:当前用第 k 张票到达 e 城市所花的最短时间;
初始值:dp[0][a] = 0;
所求为:dp[x][b];其中x为花的票数,这个是不定的;
其中含义:
将要用的票的所有情况二进制压缩出来;
然后依次枚举当前票是否用过;
没用过则可推至下一种用过这张票的情况;
而当要用这张票时,它是可以到达任意的城市的;
所以可以枚举出用了这张票以后会出现所有情况;
代码如下:
题意:
有个人要从一个城市 a 到城市 b;
其中他有 n 张马车票;
每张马车票有一个速度 t[i];
地图上有 p 条路;
每条路是双向的,并且有个距离 d[i];
他每走一条路就要花一张马车票;
一张马车票只能用于一条路;
求他所要花的最短时间;
理解:
dp 咯。。。
推不出来啊,状态压缩dp;
一看递推式含义就能明白很多了;
dp[i][j] 表示用 i 张票到达 j 城市所花的最短时间;
递推式:dp[i | (1 << k)][e] = min(dp[i | (1 << k)][e], dp[i][j] + d[j][e] / t[k]);
即:当前用第 k 张票到达 e 城市所花的最短时间;
初始值:dp[0][a] = 0;
所求为:dp[x][b];其中x为花的票数,这个是不定的;
其中含义:
将要用的票的所有情况二进制压缩出来;
然后依次枚举当前票是否用过;
没用过则可推至下一种用过这张票的情况;
而当要用这张票时,它是可以到达任意的城市的;
所以可以枚举出用了这张票以后会出现所有情况;
代码如下:
#include <cstdio> #include <cstring> #include <cmath> #include <ctime> #include <iostream> #include <algorithm> #include <vector> #include <string> #include <map> #include <set> #include <queue> #include <stack> using namespace std; typedef long long LL; typedef pair<int, int> PII; const int MIN_INF = 1e-7; const int MAX_INF = (1e9) + 7; #define X first #define Y second double dp[345][34]; //用了 i 张票到达 j 的最小值 double d[34][34]; double t[12]; int main() { int n, m, p, a, b; while (cin >> n >> m >> p >> a >> b && (n + m + p + a + b)) { for (int i = 0; i < (1 << n); ++i) { fill(dp[i], dp[i] + m + 1, MAX_INF + 1.1); } for (int i = 1; i < m + 1; ++i) { fill(d[i], d[i] + m + 1, -1); } for (int i = 0; i < n; ++i) { cin >> t[i]; } for (int i = 0; i < p; ++i) { int x, y; cin >> x >> y; cin >> d[x][y]; d[y][x] = d[x][y]; } double ans = MAX_INF + 1.1; dp[0][a] = 0; //初始值 for (int i = 0; i < (1 << n); ++i) { //枚举所有票的情况 for (int j = 1; j < m + 1; ++j) { //当前在那个位置 for (int k = 0; k < n; ++k) { //当前要用的票 if (((1 << k) & i) == 0) { //如果此票可用就继续 for (int e = 1; e < m + 1; ++e) { //用此票可到达的城市 if (d[j][e] != -1) { //此城市可达 dp[i | (1 << k)][e] = min(dp[i | (1 << k)][e], dp[i][j] + d[j][e] / t[k]); } } } } } ans = min(ans, dp[i][b]); //每次求最小值 } if (ans == MAX_INF + 1.1) { cout << "Impossible" << endl; } else { cout << ans << endl; } } return 0; }
相关文章推荐
- 详解Android应用中屏幕尺寸的获取及dp和px值的转换
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android dpi,dip,dp的概念以及屏幕适配
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题