[状压DP]P1433 吃奶酪 题解
状态压缩入门题。
状态很好想,记录一下结束的点与已经到达过的点就可以开始转移。
第一维存结束点,第二维存状态。
有一个小坑点就是不是任意点开始,而是要从 $ (0,0)$ 开始走,因此初始化的时候要赋一下初始值。(大概不会有人和我一样瞎
#include <bits/stdc++.h>
constexpr int N = 16;
using namespace std;
int n;
double ans , x[N] , y[N] , dis[N][N] , dp[N][1 << N];
int main() {
ios :: sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
ans = 114514;
memset(dp , 114514 , sizeof dp);
cin >> n;
for(register int i = 1; i <= n; ++i){
cin >> x[i] >> y[i];
dp[i][1 << i - 1] = __builtin_sqrt((x[i] * x[i]) + (y[i] * y[i]));
}
for(register int i = 1; i <= n; ++i) {
for(register int j = 1; j <= n; ++j) {
dis[i][j] = __builtin_sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
}
}
for(register int i = 1; i < (1 << n); ++i) {
for(register int j = 1; j <= n; ++j) {
if(i & (1 << j - 1)) {
for(register int k = 1; k <= n; ++k) {
if(i & (1 << k - 1)) {
dp[j][i] = min(dp[j][i] , dp[k][i ^ (1 << j - 1)] + dis[j][k]);
}
}
}
}
}
for(register int i = 1; i <= n; ++i){
ans = min(ans , dp[i][(1 << n) - 1]);
}
cout << fixed << setprecision(2) << ans;
return 0;
}