最小配对(tyvj 1196)

来源:互联网 发布:淘宝子账号哪里登陆 编辑:程序博客网 时间:2024/05/01 06:30

tyvj 1196:

因为点只有20个,用搜索就可以过,但是需要减枝一下,就是当当前计算的总距离大于已经记录的最小距离和还有大的时候,这种情况可以直接剪掉。

还有一个地方需要注意,在写的时候没注意到错了好几次。就是在搜索过程中i循环一次以后就要break,因为这题是在枚举各种组合情况,所以(a, b)(c, d)和(c, d)(a, b)其实是一样的,就不需要再重复计算。

比如说有四个点1, 2, 3, 4

程序会先搜到(1, 2)(3, 4)这种情况,如果不break的话,继续往下搜就会出现9(3, 4)(1, 2)的情况。

#include <stdio.h>#include <string.h>#include <math.h>struct node{double x, y;};node p[30];int n;double ans, dis[30][30];bool vis[30];double f(node a, node b){double c = a.x;double d = a.y;double e = b.x;double f = b.y;return (sqrt((c - e) * (c - e) + (d - f) * (d - f)));}void dfs(int c, double s){int i, j;if(c == n){if(ans > s)ans = s;return ;}for(i = 0; i < n; i++){if(vis[i] == 0){vis[i] = 1;for(j = i + 1; j < n; j++){if(vis[j] == 0 && s + dis[i][j] < ans){vis[j] = 1;dfs(c + 2, s + dis[i][j]);vis[j] = 0;}}vis[i] = 0;break;//注意这个break,保证在以后搜的情况之前没有搜到过,这里是组合不是排列}}}int main (void){while(scanf("%d", &n) != EOF){int i, j;for(i = 0; i < n; i++)scanf("%lf %lf", &p[i].x, &p[i].y);ans = 0x3f3f3f3f; memset(vis, 0, sizeof(vis));for(i = 0; i < n; i++){for(j = i + 1; j < n; j++){dis[i][j] = dis[j][i] = f(p[i], p[j]);}}dfs(0, 0.0);printf("%.2lf\n", ans);}return 0;}


0 0
原创粉丝点击