题目的大致意思就是说一个人出去遛狗 狗的速度是人的2倍 狗和人都是从同一点出发 狗会去找骨头之类的东西 人和狗都是直线运动的然后要求在人到达下一点之前狗要到达人的下一个点 求的是狗最多能到达多少个点 并输出.
初看这个题目很容易使人想到计算几何之类的东西 如果不是看分类我真的是想不到会是二分图的最大匹配问题 把人的坐标看成一个集合骨头的坐标看成另一个坐标 这样很明显了
然后构造二元关系矩阵 最后就是模板般的代码了,另外加了个父亲数组,统计输出的顺序,建图还是很巧妙.
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 110
int map[N][N],use[N],link[N],n,m;
struct Point
{
int x,y;
}Bob[N],dog[N];
double distance(Point a,Point b)
{
return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+1.0*(a.y-b.y)*(a.y-b.y));
}
bool chack(int i,int j)
{
double s1,s2,s3;
s1=distance(Bob[i],dog[j]);
s2=distance(Bob[i+1],dog[j]);
s3=distance(Bob[i],Bob[i+1]);
if(s1+s2>2*s3)
return 0;
return 1;
}
bool dfs(int x){
int i,j;
for(i=1;i<=m;i++){
if (use[i]==0&&map[x][i]) {
use[i]=1;
j=link[i];
link[i]=x;
if (j==-1||dfs(j)) {
return true;
}
link[i]=j;
}
}
return false;
}
int hungary(){
int num=0;
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
use[j]=0;
if (dfs(i))
num++;
}
return num;
}
int main()
{
int i,j,pre[N];
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d%d",&Bob[i].x,&Bob[i].y);
for(i=1;i<=m;i++)
scanf("%d%d",&dog[i].x,&dog[i].y);
memset(map,0,sizeof(map));
for(i=1;i<n;i++)
for(j=1;j<=m;j++)
{
if(chack(i,j))
{
map[i][j]=1;
}
}
/*
for(i=1;i<n;i++)
{
for(j=1;j<=m;j++)
printf("%d ",map[i][j]);
printf("\n");
}*/
memset(link,-1,sizeof(link));
printf("%d\n",n+hungary());
/*
for(i=1;i<=m;i++)
if(link[i]!=-1)
printf("%d %d %d\n",i,Bob[link[i]].x,Bob[link[i]].y);
*/
memset(pre,-1,sizeof(pre));
for(i=1;i<=m;i++)
if(link[i]!=-1)
pre[link[i]]=i;
for(i=1;i<n;i++) //输出
{
if(pre[i]==-1)
printf("%d %d ",Bob[i].x,Bob[i].y);
else
printf("%d %d %d %d ",Bob[i].x,Bob[i].y,dog[pre[i]].x,dog[pre[i]].y);
}
printf("%d %d",Bob[i].x,Bob[i].y);
printf("\n");
}
return 0;
}
poj 1034

最新推荐文章于 2021-05-18 06:14:03 发布