zoukankan      html  css  js  c++  java
  • POJ3565AntsKM变形

    题意:

    给出n个蚂蚁和苹果的坐标,对每个蚂蚁和苹果进行匹配(之间连一条线段),要求:任意两条线段不相交,输出一种方案。

    思路:

    因为三角形的两边之和大于第三边,

    所有他们连线的所有线段和最小的时候线段一定不会相交,

    所以这道题目就变成了二分图最小权值匹配,把任意两点间权值即为他们的距离,跑一遍KM即可

    注意:

    套KM模板的时候,必须从1开始记录,否则不出结果

    出来任意一种方案即可,不一定要和样例输出一样

    double类型不要弄错

    double类型比较的时候最好用<eps,因为精度问题,直接判断等于0可能会出错

    AC代码:

      1 #include<stdio.h>
      2 #include<iostream>
      3 #include<queue>
      4 #include<cmath>
      5 #include<string.h>
      6 using namespace std;
      7 #define inf 0x3f3f3f3f
      8 typedef long long ll;
      9 const int N=110;
     10 #define inf 0x3f3f3f3f
     11 #define eps 1e-9
     12 
     13 //man x、woman y
     14 int n,match[N];
     15 double love[N][N],exy[N],exx[N],need[N];//***
     16 bool booky[N],bookx[N];
     17 struct node
     18 {
     19     int x,y;
     20 } ant[N],apple[N];
     21 
     22 bool dfs(int woman)
     23 {
     24     booky[woman]=1;
     25     for(int i=1; i<=n; i++)//man
     26     {
     27         if(bookx[i])
     28             continue;
     29         double w=exy[woman]+exx[i]-love[woman][i];//***
     30         if(fabs(w)<=eps )//***
     31             // if(w==0)
     32         {
     33             bookx[i]=1;
     34             if(match[i]==-1||dfs(match[i]))
     35             {
     36                 match[i]=woman;
     37                 return 1;
     38             }
     39         }
     40         else
     41             need[i]=min(need[i],w);
     42     }
     43     return 0;
     44 }
     45 
     46 int KM()
     47 {
     48     for(int i=1; i<=n; i++)
     49     {
     50         exy[i]=inf*(-1.0);//***
     51         for(int j=1; j<=n; j++)
     52             exy[i]=max(exy[i],love[i][j]);
     53     }
     54     for(int i=1; i<=n; i++)
     55     {
     56         fill(need+1,need+n+1,inf);//***
     57         while(1)
     58         {
     59             memset(bookx,0,sizeof bookx);
     60             memset(booky,0,sizeof booky);//放在这里清空,清空和break不能掉头否则TLE
     61             if(dfs(i))
     62                 break;
     63             double minn=inf;//***
     64             for(int j=1; j<=n; j++)
     65             {
     66                 if(bookx[j]==0)
     67                     minn=min(minn,need[j]);
     68             }
     69             for(int j=1; j<=n; j++)
     70             {
     71                 if(booky[j])
     72                     exy[j]-=minn;
     73                 if(bookx[j])
     74                     exx[j]+=minn;
     75                 else
     76                     need[j]-=minn;
     77             }
     78         }
     79     }
     80 //    int sum=0;
     81 //    for(int i=0; i<n; i++)
     82 //        sum+=love[match[i]][i];
     83 //    return sum;
     84 }
     85 
     86 int main()
     87 {
     88     while(~scanf("%d",&n))
     89     {
     90         memset(match,-1,sizeof(match));
     91         memset(exx,0,sizeof exx);
     92         memset(exy,0,sizeof exy);
     93         for(int i=1; i<=n; i++)
     94             scanf("%d %d",&ant[i].x,&ant[i].y);
     95         for(int i=1; i<=n; i++)
     96             scanf("%d %d",&apple[i].x,&apple[i].y);
     97         for(int i=1; i<=n; i++)
     98         {
     99             for(int j=1; j<=n; j++)
    100 
    101                 love[j][i]=(-1.0)*sqrt((ant[i].x-apple[j].x)*(ant[i].x-apple[j].x)+(ant[i].y-apple[j].y)*(ant[i].y-apple[j].y));
    102         }
    103         KM();
    104         for(int i=1; i<=n; i++)
    105             printf("%d\n",match[i]);
    106     }
    107     return 0;
    108 }
    View Code
  • 相关阅读:
    思考:缓存的使用?灵活运用?
    线程和并发--基础
    java基础--方法
    java基础--数组
    数据结构复习笔记
    asp搭建网站
    转换磁盘格式
    cypress 与其他测试框架的区别
    cypress启动时报错file already exists,文件已经存在解决办法
    cypress的安装
  • 原文地址:https://www.cnblogs.com/OFSHK/p/12697586.html
Copyright © 2011-2022 走看看