• uva 1411 Ants


    题意:

    一个平面上有n个黑色的点,n个白色的点,要求黑色的点与白色点之间一一配对,且线段之间不相交。

    思路:

    线段不相交并不好处理,想了很久想不出,所以看了蓝书的讲解。

    一个很明显的结论是,不相交的线段一定比相交的线段短,如图:一个较为直观的例子。

    由于点之间一一对应,所以肯定用二分图匹配,然后要使得所有线段之和最短,那么就是求一个带权最小匹配,上KM算法解决。

    把所有的边权取负值,求最大匹配即可。

    代码:

      1 #include <stdio.h>
      2 #include <math.h>
      3 #include <string.h>
      4 #include <algorithm>
      5 #include <vector>
      6 using namespace std;
      7 
      8 const int N = 105;
      9 
     10 double mp[N][N];
     11 
     12 struct node
     13 {
     14     double x,y;
     15     node(double a,double b)
     16     {
     17         x = a;
     18         y = b;
     19     }
     20 };
     21 
     22 vector<node> nx,ny;
     23 
     24 bool vis_x[N],vis_y[N];
     25 int match[N];
     26 double lx[N],ly[N];
     27 double slack[N];
     28 int ma[N];
     29 
     30 double cal(int i,int j)
     31 {
     32     double dx = pow(nx[i].x - ny[j].x,2);
     33     double dy = pow(nx[i].y - ny[j].y,2);
     34     
     35     return sqrt(dx + dy);
     36 }
     37 
     38 bool dfs(int u,int n)
     39 {
     40     vis_x[u] = 1;
     41     
     42     for (int i = 0;i < n;i++)
     43     {
     44         if (vis_y[i]) continue;
     45         
     46         double gap = lx[u] + ly[i] - mp[u][i];
     47         
     48         //getchar();
     49         
     50         //printf("%.6f %.6f %.6f %.6f
    ",lx[u],ly[i],mp[u][i],gap);
     51         
     52         if (fabs(gap) < 1e-6)
     53         {
     54             vis_y[i] = 1;
     55             
     56             if (match[i] == -1 || dfs(match[i],n))
     57             {
     58                 match[i] = u;
     59                 return true;
     60             }
     61         } 
     62         else
     63         {
     64             slack[i] = min(slack[i],gap);
     65         }
     66     }
     67     
     68     return false;
     69 }
     70 
     71 void km(int n)
     72 {
     73     memset(ly,0,sizeof(ly));
     74     memset(match,-1,sizeof(match));
     75     
     76     for (int i = 0;i < n;i++)
     77     {
     78         lx[i] = mp[i][0];
     79         
     80         for (int j = 1;j < n;j++)
     81         {
     82             lx[i] = max(lx[i],mp[i][j]);
     83         }
     84     }
     85     
     86     for (int i = 0;i < n;i++)
     87     {
     88         for (int j = 0;j < n;j++) slack[j] = 1e15;
     89         //printf("gg");
     90         while (1)
     91         {
     92             //printf("233");
     93             memset(vis_x,0,sizeof(vis_x));
     94             memset(vis_y,0,sizeof(vis_y));
     95             
     96             if (dfs(i,n)) break;
     97             
     98             double d = 1e15;
     99             
    100             for (int j = 0;j < n;j++)
    101             {
    102                 if (!vis_y[j]) d = min(slack[j],d);
    103             }
    104             
    105             for (int j = 0;j < n;j++)
    106             {
    107                 if (vis_x[j]) lx[j] -= d;
    108                 
    109                 if (vis_y[j]) ly[j] += d;
    110             }
    111             
    112             //getchar();
    113             
    114             //printf("%.6f **
    ",d);
    115         }
    116     }
    117 }
    118 
    119 int main()
    120 {
    121     int n;
    122     int kase = 0;
    123     
    124     while (scanf("%d",&n) != EOF)
    125     {
    126         if (kase++) printf("
    ");
    127         
    128         nx.clear();
    129         ny.clear();
    130         
    131         for (int i = 0;i < n;i++)
    132         {
    133             double x,y;
    134             scanf("%lf%lf",&x,&y);
    135             
    136             nx.push_back(node(x,y));
    137         }
    138         
    139         for (int i = 0;i < n;i++)
    140         {
    141             double x,y;
    142             scanf("%lf%lf",&x,&y);
    143             
    144             ny.push_back(node(x,y));
    145         }
    146         
    147         for (int i = 0;i < n;i++)
    148         {
    149             for (int j = 0;j < n;j++)
    150             {
    151                 mp[i][j] = -cal(i,j);
    152             }
    153         }
    154         
    155         km(n);
    156         
    157         for (int i = 0;i < n;i++)
    158         {
    159             int a = i + 1,b = match[i] + 1;
    160             ma[b] = a;
    161         }
    162         
    163         for (int i = 0;i < n;i++)
    164         {
    165             printf("%d
    ",ma[i+1]);
    166         }
    167     }
    168     
    169     return 0;
    170 }
  • 相关阅读:
    MSSQL 链接Oracle 表
    ORACLE FORM ZA 常用子程序
    FORM 中提交报表并查看结果
    Form界面设置只读
    FRM30403
    oracle 分区表的建立方法
    在Oracle Form中,如何实现自动编号(行号)的功能
    Form中格式化数字、金额
    MSC_SYSTEM_ITEMS,mtl_system_items_b区别
    C#中判断一个字符串是不是包含非法字符
  • 原文地址:https://www.cnblogs.com/kickit/p/8809124.html
Copyright © 2020-2023  润新知