POJ 2686 Traveling by Stagecoach(状压DP)

【题目链接】 http://poj.org/problem?id=2686

【题目大意】

  给出一张无向图,你有n张马车票每张车票可以租用ti匹马,
  用一张马车票从一个城市到另一个城市所用的时间为这两个城市间的道路距离除以马的数量
  一张马车票只能用一次,问从a到b的最短时间

【题解】

  dp[S][u]表示剩余的车票集合为S,到达u所用的最短时间,
  之后我们枚举剩余的车票集合,枚举边和用的车票,进行状态转移。

【代码】

#include <cstdio>
#include <climits>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=10,M=35;
const double INF=1000000000;
int x,y,c,n,m,a,b,p,t[N],d[M][M];
double dp[1<<N][M];
int main(){
    while(~scanf("%d%d%d%d%d",&n,&m,&p,&a,&b)){
    	if(n+m+p+a+b==0)break;
        memset(d,-1,sizeof(d));
        for(int i=0;i<n;i++)scanf("%d",&t[i]);
        for(int i=1;i<=p;i++){
            scanf("%d%d%d",&x,&y,&c);
            d[x-1][y-1]=c; d[y-1][x-1]=c;
        }for(int S=0;S<1<<n;S++)fill(dp[S],dp[S]+m,INF);
        dp[(1<<n)-1][a-1]=0;
        double res=INF;
        for(int S=(1<<n)-1;S>=0;S--){
            res=min(res,dp[S][b-1]);
            for(int v=0;v<m;v++){
                for(int i=0;i<n;i++)if((S>>i)&1){
                    for(int u=0;u<m;u++){
                        if(d[v][u]>=0){
                            dp[S&~(1<<i)][u]=min(dp[S&~(1<<i)][u],dp[S][v]+(double)d[v][u]/t[i]);
                        }
                    }
                }
            }
        }if(res==INF)puts("Impossible\n");
        else printf("%.3f\n",res);
    }return 0;
}
时间: 2024-10-07 00:55:11

POJ 2686 Traveling by Stagecoach(状压DP)的相关文章

POJ 2686 Traveling by Stagecoach (状压DP)

题意:有一个人从某个城市要到另一个城市, 有n个马车票,相邻的两个城市走的话要消耗掉一个马车票.花费的时间呢,是马车票上有个速率值 ,问最后这个人花费的最短时间是多少. 析:和TSP问题差不多,dp[s][i] 表示当前在第 i 个城市,还剩余集合 s的票,需要的最短时间.状态转移方程: dp[s][i] = min{dp[s|j][k] + d[i][k] } 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000")

POJ 2686 Traveling by Stagecoach (状态压缩DP)

Traveling by Stagecoach Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 2776   Accepted: 996   Special Judge Description Once upon a time, there was a traveler. He plans to travel using stagecoaches (horse wagons). His starting point and

POJ 2411 Mondriaan&#39;s Dream(状压DP)

http://poj.org/problem?id=2411 求一个n*m矩阵用1*2方块去填满的情况有几种 思路:状压dp,先预处理那些状态之间能互相到达,情况就几种,上一个两个1,下一个状态也两个1,上一个为0,下一个必须为1,还有一种是上一个为1,下一个为0的情况 然后就一层层往后递推即可 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int

POJ 2411 Mondriaan&#39;s Dream ——状压DP 插头DP

[题目分析] 用1*2的牌铺满n*m的格子. 刚开始用到动规想写一个n*m*2^m,写了半天才知道会有重复的情况. So Sad. 然后想到数据范围这么小,爆搜好了.于是把每一种状态对应的转移都搜了出来. 加了点优(gou)化(pi),然后poj上1244ms垫底. 大概的方法就是考虑每一层横着放的情况,剩下的必须竖起来的情况到下一层取反即可. 然后看了 <插头DP-从入门到跳楼> 这篇博客,怒抄插头DP 然后16ms了,自己慢慢YY了一下,写出了风(gou)流(pi)倜(bu)傥(tong)

poj 2411 Mondriaan&#39;s Dream 状压dp入门

题意: 求h*w的矩形被1*2的小矩形覆盖的方案数. 分析: 状压dp入门,<挑战程序设计竞赛>上讲的很好,好几天才看懂. 代码: #include <iostream> using namespace std; __int64 ans[16][16]; int n,m; __int64 dp[2][1<<16]; __int64 solve() { int i,j,used; memset(dp,0,sizeof(dp)); __int64 *crt=dp[0],*n

POJ 2411 Mondriaan&#39;s Dream (状压DP)

题意:给出一个n*m的棋盘,及一个小的矩形1*2,问用这个小的矩形将这个大的棋盘覆盖有多少种方法. 析:对第(i,j)位置,要么不放,要么竖着放,要么横着放,如果竖着放,我们记第 (i,j)位置为0,(i+1,j)为1,如果横着放,那么我们记 (i,j),(i,j+1)都为1,然后dp[i][s]表示 第 i 行状态为 s 时,有多少方法,那么我们就可以考虑与和匹配的状态,这个也很容易判断. 代码如下: #pragma comment(linker, "/STACK:1024000000,102

POJ 1185 炮兵阵地(状压DP入门)

http://poj.org/problem?id=1185 状压DP: 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int dp[105][100][100]; 7 int ma[105],st[105]; 8 9 int ok(int x) 10 { 11 return (x&(x<<1))+(x&(x&

POJ 3254 Corn Fields 【状压DP】

[题目大意]一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻.问有多少种放牛方案(一头牛都不放也是一种方案) [解析]根据题意,把每一行的状态用二进制的数表示,0代表不在这块放牛,1表示在这一块放牛.首先很容易看到,每一行的状态要符合牧场的硬件条件,即牛必须放在能放牧的方格上.这样就能排除一些状态.另外,牛与牛之间不能相邻,这样就要求每一行中不能存在两个相邻的1,这样也能排除很多状态.

POJ 3254 Corn Fields //入门状压dp

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7578   Accepted: 4045 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yumm

poj 2441 Arrange the Bulls 状压dp入门

题意: 将n头牛和m个栏做匹配,求匹配方案数. 分析: 开始暴搜tle了,还是要用状压dp,dp[i][s]表示前i头牛匹配栏的状态为s时可行的方案数. 代码: //poj 2441 //sep9 #include <iostream> using namespace std; const int maxN=21; int dp[2][1<<maxN]; int a[maxN][maxN]; int main() { int n,m; scanf("%d%d",