POJ2686 Traveling by Stagecoach 状态压缩DP

POJ2686

比较简单的 状态压缩DP 

注意DP方程转移时,新的状态必然数值上小于当前状态,故最外层循环为状态从大到小即可。

#include <cstdio>  
#include <algorithm>  
#include <cstring>  
using namespace std;  
const int maxn = 1 << 10;  
const int maxm = 31;  
const int INF = 1 << 29;  
  
int n, m, p, a, b;  
int t[maxm];  
int d[maxm][maxm];   //图的邻接矩阵表示(-1表示没有边)  
  
//dp[S][v] := 到达剩下的车票集合为S并且现在在城市v的状态所需要的最小花费  
double dp[maxn][maxm];  
  
void solve()  
{  
    for (int i = 0; i < (1 << n); i++)  
        fill(dp[i], dp[i] + m + 1, INF);    //用足够大的值初始化  
  
    dp[(1 << n) - 1][a] = 0;  
    double res = INF;  
    for (int i = (1 << n) - 1; i >= 0; i--){  
        for (int u = 1; u <= m; u++){  
            for (int j = 0; j < n; j++){  
                if (i & (1 << j)){  
                    for (int v = 1; v <= m; v++){  
                        if (d[v][u]){  
                            //使用车票i,从v移动到u  
                            dp[i & ~(1 << j)][v] = min(dp[i & ~(1 << j)][v], dp[i][u] + (double)d[u][v] / t[j]);  
                        }  
                    }  
                }  
            }  
        }  
    }  
    for (int i = 0; i < (1 << n); i++)  
        res = min(res, dp[i][b]);  
    if (res == INF)  
        //无法到达  
        printf("Impossible
");  
    else  
        printf("%.3f
", res);  
  
}  
  
int main()  
{  
    while(scanf("%d%d%d%d%d", &n, &m, &p, &a, &b)!= EOF){  
        if(!n && !m)  
        break;  
        memset(d, 0, sizeof(d));  
        for (int i = 0; i < n; i++)  
            scanf("%d", &t[i]);  
        for (int i = 0; i < p; i++){  
            int u, v, c;  
            scanf("%d%d%d", &u, &v, &c);  
            d[u][v] = d[v][u] = c;  
        }  
        solve();  
    }  
    return 0;  
}  

  

原文地址:https://www.cnblogs.com/heisenberg-/p/6882580.html