ZJU2039 The Dog Task - 二部图最大匹配

来源:互联网 发布:幼儿园手指数算法视频 编辑:程序博客网 时间:2024/05/16 19:10

题目大意:

Bob带着他的Dog外出散步,Bob速度固定且依次沿着n个点行走,分别用(Xi,Yi)表示。Dog的速度可以达到Bob的2倍。在路途中有m个地点是Dog喜欢玩耍的地方,用(Xi',Yi')表示。Dog和Bob同时从第一个点X1,Y1出发,Dog在路途中跑去玩耍,但是必须在Bob到达第二个点X2,Y2时赶回来和Bob碰面。每次离开Bob,Dog最多只能去一个地方玩耍,以前去过的地方Dog不会再去。输入Bob的行走路线的n个点,和Dog喜欢玩耍的m个点,要求Dog最多能去多少地方玩耍并输出他的路线。

分析:

网上有些题目分类说这是个计算几何题。>_<显然,做分类的这个家伙一定没有读过题。

Bob路线上的n个点可以看作是n-1条线段。对于每条线段来说,只要Dog从起点出发去某个地点P玩耍后回到终点的总路程s,大于这条线段的长度,那么Dog就可以去P玩耍。

用n-1条线段和m个玩耍地点做一个二部图若g[i][j]有边相连,表示行走第i条线段时可以去地点j玩耍。然后求这个二部图g[n-1][m]的最大匹配即可。

----------------------------------------------------

/*
ZJU2039 The Dog Task
*/

#include <stdio.h>
#include <math.h>
#include <memory.h>
#define clr(a) memset(a,0,sizeof(a))

#define N 105

typedef struct{
    int x,y;
}Point;

//functions
double distance(Point p1,Point p2){
    return sqrt( (p1.x-p2.x)*(p1.x-p2.x)
                +(p1.y-p2.y)*(p1.y-p2.y));
}

int find(int i,int m,int g[][N],int mat[],int tmat[]){
    int v,j;
    for(j=0;j<m;j++)
        if(g[i][j]&&tmat[j]==0){
            tmat[j]=1;v=mat[j];
            mat[j]=i;
            if(v==-1||find(v,m,g,mat,tmat)) return 1;
            mat[j]=v;
        }
    return 0;
}

int match(int g[][N],int n,int m,int mat[]){
    int i,k=0;
    int tmat[N];
    for(i=0;i<m;i++) mat[i]=-1;
    for(i=0;i<n;i++){
        memset(tmat,0,sizeof(tmat));
        k+=find(i,m,g,mat,tmat);
    }
    return k;
}

int main()
{
    int i,j,k,m,n,T;
    double s,s1,s2;
    Point Bob[N];
    Point tree[N];
    int g[N][N];
    int mat[N];
   
    scanf("%d",&T);
    while(T--){

        //input
        scanf("%d%d",&n,&m);
        for(i=0;i<n;i++)
            scanf("%d%d",&Bob[i].x,&Bob[i].y);
        for(i=0;i<m;i++)
            scanf("%d%d",&tree[i].x,&tree[i].y);
       
        //creat map
        clr(g);
        for(i=0;i<n-1;i++){
            s=distance(Bob[i],Bob[i+1])*2.0;
            for(j=0;j<m;j++){
                s1=distance(Bob[i],tree[j]);
                s2=distance(Bob[i+1],tree[j]);
                if(s>s1+s2) g[j][i]=1;
            }
        }
       
        //match
        k=match(g,m,n-1,mat);
       
        //output
        printf("%d/n",n+k);
        for(i=0;i<n-1;i++){
            printf("%d %d ",Bob[i].x,Bob[i].y);
            if(mat[i]!=-1)
                printf("%d %d ",tree[mat[i]].x,tree[mat[i]].y);
        }
        printf("%d %d/n",Bob[i].x,Bob[i].y);
       
        if(T) puts("");
    }
   
    return 0;
}

/*

2

4 5
1 4 5 7 5 2 -2 4
-4 -2 3 9 1 2 -1 3 8 -3

*/

原创粉丝点击