ABC274E
[[Bitmask DP]]
link: E - Booster
看到这么小的数据量,就知道这是个状压DP了
状态 \(f_{i,D}\) 表示当前在点 \(i\) ,已经到过了集合 \(D\) 时的最短时间
转移方式是每次多到一个点,所以可以用BFS实现,每次扩展一层就是多到一个点
然后花费要乘上一个与集合 \(D\) 相关的系数 \(fx\)
赛时代码:
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int n,m,x[N],y[N],S,SS,u,D;
double dis[18][1<<17],fx[6],xx,ans=1e18;
using pii=pair<int,int>;
queue<pii>q;
double ds(double a,double b){
return sqrt(a*a+b*b);
}
int main(){
fx[0]=1;
for(int i=1;i<=5;i++)fx[i]=fx[i-1]/2;
scanf("%d%d",&n,&m);
S=(1<<n)-1;
for(int i=n;i<n+m;i++)SS+=1<<i;
for(int i=0;i<1<<n+m;i++)for(int j=0;j<n+m;j++)dis[j][i]=1.1e18;
for(int i=0;i<n+m;i++)scanf("%d%d",x+i,y+i),dis[i][1<<i]=ds(x[i],y[i]),q.push({i,1<<i});
while(!q.empty()){
tie(u,D)=q.front();q.pop();
xx=fx[__builtin_popcount(SS&D)];
for(int i=0;i<n+m;i++)if(!(D>>i&1)){
if(dis[i][D|(1<<i)]>1e18)q.push({i,D|(1<<i)});
if(dis[i][D|(1<<i)]>dis[u][D]+xx*ds(abs(x[i]-x[u]),abs(y[i]-y[u])))dis[i][D|(1<<i)]=dis[u][D]+xx*ds(abs(x[i]-x[u]),abs(y[i]-y[u]));
}
}
for(int i=0;i<1<<m;i++){
xx=fx[__builtin_popcount(i)];
for(int u=0;u<n+m;u++){
if(u>=n&&i>>(u-n)&1)ans=min(ans,dis[u][S+(i<<n)]+xx*ds(x[u],y[u]));
if(u<n)ans=min(ans,dis[u][S+(i<<n)]+xx*ds(x[u],y[u]));
}
}
printf("%.11lf",ans);
}

浙公网安备 33010602011771号