少量位运算使用理解
第 i 位为从右往左从0开始数
如果要设置 n 的第 i 位为1,n=(n|(1<<i);
如果要设置 n 的第 i 位为0,n=(n &(~(1<<i));
& 按位与
如果两个相应的二进制位都为1,则该位的结果值为1,否则为0
l 按位或
两个相应的二进制位中只要有一个为1,该位的结果值为1
^ 按位异或
若参加运算的两个二进制位值相同则为0,否则为1
~ 取反
~是一元运算符,用来对一个二进制数按位取\反,即将0变1,将1变0
<< 左移
用来将一个数的各二进制位全部左移N位,右补0
( >> 右移
将一个数的各二进制位右移N位,移到右端 的低位被舍弃,对于无符号数,高位补0
题干
有一个人从某个城市要到另一个城市(点数<=30)
然后有n个马车票,相邻的两个城市走的话要消耗掉一个马车票。
花费的时间呢,是马车票上有个速率值,用边/速率是花的时间。
求最后这个人花费的最短时间是多少
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=35;
const int INF=1e9;
double dp[1<<10][maxn];
int mp[maxn][maxn];
int d[maxn];
int main(){
int t,n,m,src,des;
while(cin>>t>>n>>m>>src>>des&&(t+n+m+src+des)){
memset(mp,-1,sizeof(mp));
for(int i=0;i<t;i++) cin>>d[i];
for(int i=1;i<=m;i++) {
int st,ed,dis;
cin>>st>>ed>>dis;
if(mp[st][ed]==-1||mp[st][ed]>dis){
mp[st][ed]=dis;
mp[ed][st]=dis;
}
}
for(int i=0;i<(1<<9);i++){
for(int j=0;j<maxn;j++) dp[i][j]=INF;
}
dp[0][src]=0;
double ans=INF;
for(int i=0;i<(1<<t);i++){//
for(int u=1;u<=n;u++){
for(int k=0;k<t;k++){
if(!(i&(1<<k))){//取票不冲突重复
for(int j=1;j<=n;j++){
if(mp[u][j]!=-1)dp[i|(1<<k)][j]=min(dp[i|(1<<k)][j],dp[i][u]+1.0*mp[u][j]/d[k]);
}
}
}
}
ans=min(ans,dp[i][des]);
}
if(ans==INF) cout<<"Impossible\n";
else printf("%.3f\n",ans);//poj %lf wa飞。。。 看discuss 才知道poj坑人。。
}
return 0;
}