P1433 吃奶酪 题解 状态压缩 DP
程序员文章站
2024-03-23 23:03:22
...
日常深夜更博 又是因为把n写成了数字找bug找了半天 哭
这道题一开始我用dfs写了,但是最后一个数据点没过
然后木有办法就只能再学一次状态压缩,写出来了
思路在代码里:
#include<bits/stdc++.h>
#define inf 99999999
using namespace std;
double dp[1<<15][20]; //dp数组,第一项表示每个状态,第二项该状态最后一步是哪个位置
double dis[20][20]; //记录两点之间的距离,邻接矩阵
int n;
struct point{
double x, y;
}p[30];
void init(){ //初始化函数
cin>>n;
p[0].x = 0.00, p[0].y = 0.00;
memset(dp, 127, sizeof(dp)); //将dp数组初始化为最大值
for(int i=1; i<=n; i++){ //输入每个点横纵坐标
cin>>p[i].x>>p[i].y;
}
for(int i=0; i<=n; i++){ //计算每两点间的距离
for(int j=i+1; j<=n; j++){
double w = sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
dis[i][j] = dis[j][i] = w;
}
}
for(int i=0; i<n; i++){ //用(0,0)到其余各点的距离初始化dp数组
dp[1<<i][i] = dis[0][i+1];
}
}
void dpFuc(){
for(int i=1; i<(1<<n)-1; i++){ // 每种状态
for(int pre=0; pre<n; pre++){ //前一位置
if(!(i&(1<<pre))) //跳过还没走过的位置
continue;
for(int now=0; now<n; now++){ //当前位置
if((i&(1<<now))) //跳过已经走过的位置
continue;
//dp数组值取新状态 和 原状态加两点间距离 中最小的一个
dp[i|(1<<now)][now] = min(dp[i|(1<<now)][now], dp[i][pre] + dis[now+1][pre+1]);
}
}
}
}
void print(){ //找出最小值并打印
double ans = inf;
for(int i=0; i<n; i++){
ans = min(ans, dp[(1<<n)-1][i]);
}
printf("%.2f", ans);
}
int main(){
init();
dpFuc();
print();
}
推荐阅读