题解
2026-08-05 14:25:03
发布于:浙江
28阅读
0回复
0点赞
别看n最大只有15,暴力dfs的时间复杂度有!n肯定会超,所以只能掏出我们的状压dp了。
用二进制下的每一位上的1来表示有没有吃过这块奶酪
#include<iostream>
#include<cmath>
int n;
std::pair<double,double>pos[20];//奶酪位置
double dis(int x,int y){
double x1=pos[x].first-pos[y].first;
double y1=pos[x].second-pos[y].second;
return sqrt(x1*x1+y1*y1);
}//计算两点间距离
double dp[1<<15|1][15];
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf%lf",&pos[i].first,&pos[i].second);
//初始化极大值
for(int i=0;i<1<<n;i++)
for(int j=0;j<n;j++)
dp[i][j]=2147483647;
pos[19]={0,0};
for(int j=0;j<n;j++){
//从(0,0)走到底j块蛋糕
dp[0|1<<j][j]=dis(19,j);
}
for(int mask=1;mask<1<<n;mask++){//mask表示具体吃了那些奶酪
for(int j=0;j<n;j++){
//吃了那些奶酪
if(mask & (1<<j)){
//从dp[mask][j]出发去吃别的奶酪
for(int k=0;k<n;k++){
//吃别的奶酪
if(!(mask & (1<<k))){//没吃过
//从第j块奶酪出发走到第j块奶酪
//状态的第k位变成1,代表吃掉底k块奶酪
dp[mask|(1<<k)][k]=std::min(dp[mask|(1<<k)][k],dp[mask][j]+dis(j,k));
}
}
}
}
}
//最后吃完所有的奶酪,停留在某个奶酪上
double ans=2147483647;
for(int i=0;i<n;i++)
ans=std::min(ans,dp[(1<<n)-1][i]);
printf("%.2lf",ans);
return 0;
}
这里空空如也





有帮助,赞一个