poj 3565 ants

/*
poj 3565 递归分治
还有用KM的做法
这里写的分治 按紫书上的方法
不过那里说的有点冗杂了
可以简化一下 
首先为啥可以分治 也就是分成子问题解决
只要有一个集合 黑白的个数相等 就一定能一一匹配
这个应该比较明显
因为是special judge 
所以我们只要保证每次处理的集合黑白相等就好了 
关键是怎么分
我们找到最下最左的点 作为基点 
然后将其他的按照连线与横坐标夹角的大小排序
这样就相当于那个线逆时针扫一遍 
当扫过去的黑白相等(都为0也可以)并且当前这个可以和基点不同色
也就是他俩能匹配 那显然当前这三部分 (扫过去的 没扫的 还有这条线)
都满足黑白相等 也就是说都能独立的匹配
然后分治就好了 
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define maxn 210
using namespace std;
int n,match[maxn];
struct node{
    int x,y,c,v;
}p[maxn],bas;
int cmp1(const node &a,const node &b){
    return (a.y==b.y&&a.x<b.x)||a.y<b.y;
}
int cmp2(const node &a,const node &b){
    double A=atan2(double(a.y-bas.y),double(a.x-bas.x));
    double B=atan2(double(b.y-bas.y),double(b.x-bas.x));
    return A<B;
}
void Dfs(int l,int r){
    if(l>r)return;
    sort(p+l,p+r+1,cmp1);
    bas=p[l];
    sort(p+l+1,p+r+1,cmp2);
    int s1=0,s2=0,k=l+1;
    while(s1!=s2||p[k].c==bas.c){
        if(p[k].c==bas.c)s1++;
        else s2++;k++;
    }
    if(bas.c==1)match[bas.v]=p[k].v;
    else match[p[k].v]=bas.v;
    Dfs(l+1,k-1);Dfs(k+1,r);
}
int main()
{
    scanf("%d",&n);
    memset(match,0,sizeof(match));
    for(int i=1;i<=n;i++){
        scanf("%d%d",&p[i].x,&p[i].y);
        p[i].c=1;p[i].v=i;
    }
    for(int i=1+n;i<=n+n;i++){
        scanf("%d%d",&p[i].x,&p[i].y);
        p[i].c=2;p[i].v=i-n;
    }
    Dfs(1,n+n);
    for(int i=1;i<=n;i++)
        printf("%d\n",match[i]);
    return 0;
}

 

posted @ 2016-10-18 17:50  一入OI深似海  阅读(221)  评论(0编辑  收藏  举报