You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
3.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;//无穷大
const int N = 16; //对于全部的测试点,保证 1<=n<=15
int n; //一共多少个奶酪
double res = INF; //记录最短路径长度,也就是最终的答案
double dis[N][N]; //dis[i][j]记录第i个点到第j的点的距离.这个是预处理的二维数组,防止重复计算,预处理是搜索优化的重要手段
bool vis[N]; //记录i奶酪在当前的路径探索中是否已经尝试过(可以重复使用噢~)
//坐标
struct Point {
double x, y;
} a[N];
//状态压缩
//一维:代表已经走过的节点有哪些,是一个二进制转为十进制的数字,最终表现为十进制.
// 每一位代表一个奶酪比如一共有3个奶酪f[(101)二进制] =f[5] 表示1号和3号奶酪吃完了2号没有吃
// 二维:代表当前的出发点
// 值f[i][j] 如果以前计算过在以第j个位置出发在前面已经完成i这种二进制表示法的节点完成情况下最短的距离是多少
double f[1 << N][N];
/**
*
* @param pos 当前的位置
* @param status 当前状态压缩表示吃到的奶酪的状态[之前都吃了谁?]eg:status=10010,代表吃了第二个和第五个奶酪(从右往左)
* @param num 已经吃掉了几个奶酪
* @param len 当前距离
*/
void dfs(int pos, int num, int st, double len) {
//剪一下枝
if (len >= res) return;
//表示n个都吃完了可以进行路线长短对比了
if (num == n) {
res = min(len, res);
return;
}
//从pos出发向1~n个奶酪进军去吃~
for (int i = 1; i <= n; i++) {
//回溯算法的套路,如果在本次寻找过程中,没有走过这个节点
//注意:深度优先一直思考的是下一个动作,下一个动作,下一个动作,重要的话说三遍!
//(1)、i就是下一个点如果选择了i,那么就要状态就会变成加入i的样子int nst = st + (1 << (i - 1));
//(2)、如果以前记录过这个状态,那么现在有没有机会去更新它?更新的条件是比它小。
if (!vis[i]) {
int nst = st + (1 << (i - 1));//目标状态,也就是要走完第i个结点之后的状态比如i=1就是2^0=1,描述状态用 1<<(i-1)噢~
//f[x][y]一路保存最小值,能用上就干掉一大批!
if (f[nst][i] && f[nst][i] <= len + dis[pos][i]) continue;
//标识状态
vis[i] = true;
//更新当前状态的值
f[nst][i] = len + dis[pos][i];
//继续深搜
dfs(i, num + 1, nst, f[nst][i]);
//取消标识
vis[i] = false;
}
}
}
int main() {
//老鼠的原始位置
a[0].x = 0, a[0].y = 0;
//读入奶酪的坐标
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i].x >> a[i].y;
//预处理(dfs能进行预处理的尽量预处理)
for (int i = 0; i <= n; i++)
for (int j = i + 1; j <= n; j++) {
double x1 = a[i].x, y1 = a[i].y, x2 = a[j].x, y2 = a[j].y;
dis[j][i] = dis[i][j] = sqrt(abs((x1 - x2) * (x1 - x2)) + abs((y1 - y2) * (y1 - y2)));
}
//深度优先搜索
dfs(0, 0, 0, 0);
//输出
printf("%.2f", res);
return 0;
}