poj 2686

来源:互联网 发布:怎么启用flash插件 mac 编辑:程序博客网 时间:2024/05/29 04:20

状态压缩dp,递推方程 :

n很小,考虑状态压缩dp。

d[s][u] 表示现在在城市u, 还剩下集合为s的车票没有用.

d[s\{i}][v] = min( dp[s][u] + d[u][v] / t[i]) 四个变量,很可能需要四重循环,现在确定递推顺序,s逆序推理,由于后序变量是在前一层变量的基础上进行选取,u, v, i的相对循环位置没有影响,随意即可。

#include<cstdio>#include<cmath>#include<stdlib.h>#include<map>#include<set>#include<time.h>#include<vector>#include<queue>#include<string>#include<string.h>#include<iostream>#include<algorithm>using namespace std;#define eps 1e-8#define INF 0x3f3f3f3f#define max(a,b) ((a)>(b)?(a):(b))#define min(a,b) ((a)<(b)?(a):(b))#define max_n 8#define max_m 32int n, m, p, S, T;int t[10];int d[max_m][max_m];double dp[1<<max_n][max_m];void solve(){    double res = INF;    for(int i=0; i<(1<<n); i++)        fill(dp[i], dp[i]+m+1, INF);    dp[(1<<n)-1][S] = 0;    for(int s=(1<<n)-1; s>=0; s--)    {        for(int u=1; u<=m; u++)            for(int i=0; i<n; i++)                if(s>>i & 1)                    for(int v=1; v<=m; v++)                        if(d[u][v] != INF)                            dp[s-(1<<i)][v] = min(dp[s-(1<<i)][v], dp[s][u]+(double)d[u][v]/t[i]);    }    for(int s=(1<<n)-1; s>=0; s--)        res = min(res, dp[s][T]);    if(res != INF)    printf("%.3lf\n", res);    else printf("Impossible\n");}int main(){    while(scanf("%d%d%d%d%d", &n, &m, &p, &S, &T) && n)    {        memset(d, 0x3f, sizeof(d));        for(int i=0; i<n; i++)            scanf("%d", &t[i]);        int u, v, w;        for(int i=0; i<p; i++)        {            scanf("%d%d%d", &u, &v, &w);            d[u][v] = d[v][u] = w;        }        solve();    }    return 0;}/*3 4 3 1 43 1 21 2 102 3 303 4 202 4 4 2 13 12 3 31 3 34 1 24 2 52 4 3 4 15 51 2 102 3 103 4 101 2 0 1 218 5 10 1 52 7 1 8 4 5 6 31 2 52 3 43 4 74 5 31 3 252 4 233 5 221 4 452 5 511 5 990 0 0 0 0*/


1 0
原创粉丝点击