状压DP<poj2686>

题意是有一个人去旅游,有n张马票,每张上面有ai头马。

给一个有向图,走每条边的费用是长度/马票的马数量,由此可见走到同一个点会有不同的马票,也就是状态不同,需要表示这种多状态只有用状压来解决,

用二进制表示状态后用正常的最短路SPFA跑一遍即可。

#include <queue>
#include<iostream>
#include<stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <ctime>
#include <vector> 
#include <queue>
using namespace std;
struct ttt{
	int p,d;
};
int n;
double dist[1<<8+5][35];//有的票和到的点 
double pp[35];
vector<int>map1[35];
double map2[35][35];
int main(){
	//freopen("in.txt","r",stdin);
	//freopen("output.txt","w",stdout);
    int i,j,k,l,t1,t2,t3,m;
    int l1,l2,l3,f4,f5;
    int sum1;
    int s1;
    while(scanf("%d %d %d %d %d",&n,&m,&t2,&s1,&t1)==5&&(n||m||t2||s1||t1)){
	memset(map1,0,sizeof(map1));
	for(i=0;i<=1<<n;i++)
		for(j=0;j<=m;j++)
			dist[i][j]=1e9+7;
	for(i=0;i<n;i++)
		cin >> pp[i];
		int f1,f2;
		double f3;
		for(i=1;i<=t2;i++){
			cin >> f1>> f2>> f3;
			map1[f1].push_back(f2);
			map1[f2].push_back(f1);
			map2[f1][f2]=f3;
			map2[f2][f1]=f3;
		}
	queue<ttt>qq;
	ttt u,v;
	u.p=(1<<n)-1; //表示全部票都有 
	u.d=s1;
	qq.push(u);
	dist[u.p][u.d]=0;
	while(!qq.empty()){
		v=qq.front();qq.pop();
		for(i=0;i<n;i++){
		if(v.p>>i&1){  //有i这个票
			for(j=0;j<map1[v.d].size();j++){
			int uu=map1[v.d][j]; //vv为距离 
		if(dist[v.p][v.d]+map2[v.d][uu]/pp[i]<dist[v.p&~(1<<i)][uu]){;
			u.p=v.p&~(1<<i); //这张票已经给用掉了
			u.d=uu;
			dist[u.p][uu]=dist[v.p][v.d]+map2[v.d][uu]/pp[i];
			qq.push(u);
		}
	}

}

}
}
	double min1=1e9+7;
	for(i=0;i<1<<n;i++)
	min1=min(min1,dist[i][t1]);
	if(min1!=1e9+7)
	printf("%.3f\n",min1);
	else
	cout << "Impossible"<<endl;
}
  	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值