POJ 2686(状压DP

题目:

大意是有一个人从某个城市要到另一个城市(点数<=30)

然后有n个马车票,相邻的两个城市走的话要消耗掉一个马车票。

花费的时间呢,是马车票上有个速率值,用边/速率就是花的时间。

问最后这个人花费的最短时间是多少

第一次做状压感觉那一长串for显示了这是个多么暴力的算法呢。。。1A了倒是挺顺的

#include<iostream>

#include<cstdio>

#include<algorithm>

#include<queue>

#include<utility>

#include<vector>

#include<cstring>

#include<cmath>

#define INF 0x3fffffff

#define pb push_back

#define pn(x) cerr<<x<<endl



using namespace std;

typedef long long ll;

const int maxv=100005;



int n,m,p,a,b;

int t[10];

int G[35][35];

double dp[35][1<<9];////记录顶点和用掉的票的集合

int main(){

////freopen("in.txt","r",stdin);

    //freopen("out.txt","w",stdout);

    while(cin>>n>>m>>p>>a>>b){

        memset(G,0,sizeof G);

        if(!(n||m||p||a||b)) break;

        for(int i=0;i<n;i++) cin>>t[i];

        for(int i=0;i<p;i++){

            int v1,v2,w;

            scanf("%d%d%d",&v1,&v2,&w);

            G[v1][v2]=G[v2][v1]=w;

        }

        for(int i=0;i<35;i++) 

            for(int j=0;j<1<<9;j++) dp[i][j]=1e10;

        dp[a][0]=0;

        for(int used=0;used<1<<n;used++)

            for(int i=1;i<=m;i++)

                for(int j=0;j<n;j++)

                    if(used&1<<j)

                        for(int k=1;k<=m;k++)

                            if(G[i][k])

                                dp[k][used]=min(dp[k][used],dp[i][used&~(1<<j)]+G[i][k]/(double)t[j]);

        double ans=1e11;

        for(int i=0;i<1<<n;i++) ans=min(ans,dp[b][i]);

        if(ans>1e9) cout<<"Impossible"<<endl;

        else cout<<ans<<endl;

    }

    return 0;

}

 

你可能感兴趣的:(poj)