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);
}
posted @ 2022-12-11 11:47  -WD-  阅读(72)  评论(0)    收藏  举报