洛谷 P1433 吃奶酪-普及+/提高
题目描述
房间里放着 nnn 块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 (0,0)(0,0)(0,0) 点处。
输入格式
第一行有一个整数,表示奶酪的数量 nnn。
第 222 到第 (n+1)(n + 1)(n+1) 行,每行两个实数,第 (i+1)(i + 1)(i+1) 行的实数分别表示第 iii 块奶酪的横纵坐标 xi,yix_i, y_ixi,yi。
输出格式
输出一行一个实数,表示要跑的最少距离,保留 222 位小数。
输入输出样例 #1
输入 #1
4
1 1
1 -1
-1 1
-1 -1
输出 #1
7.41
说明/提示
数据规模与约定
对于全部的测试点,保证 1≤n≤151\leq n\leq 151≤n≤15,∣xi∣,∣yi∣≤200|x_i|, |y_i| \leq 200∣xi∣,∣yi∣≤200,小数点后最多有 333 位数字。
提示
对于两个点 (x1,y1)(x_1,y_1)(x1,y1),(x2,y2)(x_2, y_2)(x2,y2),两点之间的距离公式为 (x1−x2)2+(y1−y2)2\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}(x1−x2)2+(y1−y2)2。
2022.7.132022.7.132022.7.13:新增加一组 Hack\text{Hack}Hack 数据。
solution
用二进制整数表示老鼠的状态,即哪些位置去过1 ,哪些位置没去过0,
对于所有没去过的地方,用当前的距离刷新一下最小距离。其实就是动态规划,只不过用二进制存储状态进行简化
代码
#include <sstream>
#include "iostream"
#include "math.h"
#include "algorithm"
#include "string.h"
#include "unordered_set"
#include "deque"
#include "stack"
#include "queue"
#include "vector"
#include "unordered_map"using namespace std;
double F[20][34000];
double dis[20][20];
double x[20], y[20];int main() {int n;cin >> n;for (int i = 1; i <= n; i++) {cin >> x[i] >> y[i];}for (int i = 0; i <= n; i++) {for (int j = i + 1; j <= n; j++) {dis[i][j] = dis[j][i] = sqrt(pow(x[i] - x[j], 2) + pow(y[i] - y[j], 2));}}memset(F, 127, sizeof(F));for (int i = 1; i <= n; i++) {F[i][1 << (i - 1)] = dis[0][i];}for (int k = 1; k < (1 << n); k++) {for (int i = 1; i <= n; i++) {if ((k & (1 << (i - 1))) == 0) continue;for (int j = i + 1; j <= n; j++) {if ((k & (1 << (j - 1))) == 0) continue;F[i][k] = min(F[i][k], F[j][k - (1 << (i - 1))] + dis[i][j]);F[j][k] = min(F[j][k], F[i][k - (1 << (j - 1))] + dis[i][j]);}}}double ans = F[0][0];for (int i = 1; i <= n; i++) {ans = min(ans, F[i][(1 << n) - 1]);}printf("%.2f", ans);return 0;
}