【洛谷习题】吃奶酪
题目链接:https://www.luogu.org/problemnew/show/P1433
之前还整理过搜索剪枝方面的技巧,但真正做题的时候却想不到。。。
这道题显然可以进行最优性剪枝,当发现现在统计的路径长度比之前求出的可能的答案还要大时,剪枝。当然复杂度比较玄学。个人感觉这题像是TSP问题的弱化版,以后可以尝试用状压DP做一下。
有一个读题方面的细节,题目里说了,坐标是实数,不一定是整数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cmath> 3 4 const int maxn = 20; 5 6 int n, vis[maxn]; 7 double x[maxn], y[maxn], d[maxn][maxn], ans = 1e9; 8 9 inline double min(double a, double b) {return a < b ? a : b;} 10 11 inline double pw2(double x) {return x * x;} 12 13 inline double dis(int i, int j) { 14 return sqrt(pw2(x[i] - x[j]) + pw2(y[i] - y[j])); 15 } 16 17 void dfs(int i, int last, double sum) { 18 if (i == n + 1) {ans = min(ans, sum);return;} 19 if (sum > ans) return; //最优性剪枝 20 for (int p = 1; p <= n; ++p) 21 if (!vis[p]) { 22 vis[p] = 1; 23 dfs(i + 1, p, sum + d[last][p]); 24 vis[p] = 0; 25 } 26 } 27 28 int main() { 29 scanf("%d", &n); 30 for (int i = 1; i <= n; ++i) scanf("%lf%lf", &x[i], &y[i]); 31 for (int i = 0; i < n; ++i) 32 for (int j = i + 1; j <= n; ++j) 33 d[i][j] = d[j][i] = dis(i, j); 34 dfs(1, 0, 0); 35 printf("%.2f", ans); 36 return 0; 37 }