POJ 2536 地鼠(二分图最大匹配)

博客介绍了如何使用二分图最大匹配的方法解决POJ 2536问题,即在老鹰逼近的情况下,帮助地鼠找到最近的地鼠洞以减少损失。输入包含地鼠和地鼠洞的坐标,要求计算至少会被吃掉的地鼠数量。通过计算地鼠到地鼠洞的距离,并进行最大匹配,可以得出答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目描述】
    草原某片区域上有 N 个地鼠正在地面寻食,附近有 M 个地鼠洞,地鼠和地鼠洞的当前位置用坐标(x,y)表示。每个洞只能容纳一个地鼠。

    一只老鹰正飞向这里,如果地鼠在 S 秒内没有进入地鼠洞,则会被老鹰吃掉。所有地鼠都以同一速度 V 进行逃生。请你帮地鼠家族设计一个优秀的逃生策略,使得损失的地鼠最少。

【输入格式】

    输入包含多组数据。
    每组数据的第一行包含四个不超过100的正整数:N,M,S,V。
    接下来的n行,每行两个实数,表示一个地鼠的坐标;
    接下来M行,每行两个实数,表示一个地鼠洞的坐标。
    所有的距离单位是“米”,所有的时间单位是“秒”,所有的速度单位是“米/秒”。

【输出格式】
    对每组数据输出一行,一个整数,表示至少要被老鹰吃掉的地鼠的数量。

【输入样例】
2 2 5 10 
1.0 1.0 
2.0 2.0 
100.0 100.0 
20.0 20.0


【输出样例】

1

 

    这就是二分图最大匹配的板题,只用找出每只地鼠能到达的所有洞的距离,再将洞与地鼠进行最大匹配,最后输出总数-匹配数就是答案。

贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 105
int n,m,s,v;
int match[N];                                          //表示i点是否已经匹配
int map[N][N];                                         //表示i号地鼠能否到达j号洞
bool visit[N];                                         //表示在一次匹配中是否被访问过
struct node{                                           //a记录地鼠坐标,b记录洞的坐标
	double x,y;
};
node a[N],b[N];

double dis(double x1,double y1,double x2,double y2)    //计算地鼠与洞之间的距离
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

bool dfs(int v)                                        //搜索洞v和地鼠i
{
     int tmp;
     for(int i=1;i<=n;i++)
         if(map[i][v]&&!visit[i])                      //寻找v的对应点且该点没有尝试过更改匹配
         {
		visit[i]=true;                         //设置访问标记 
		tmp=match[i];                          //保存i原匹配点     
		match[i]=v;                            //压入新匹配点        
		if(tmp==0||dfs(tmp))                   //如果是初始值则增广成功返回
		  return true; 
		match[i]=tmp;                          //如果失败就重新找点增广,恢复i点原匹配
         }
     return false;                                     //i点无法增广    
}


int main()
{
    while(scanf("%d%d%d%d",&n,&m,&s,&v)!=EOF)          //因为是多组数据所以用while读入
    {        
        memset(match,0,sizeof(match));
        memset(map,0,sizeof(map)); 
	for(int i=1;i<=n;i++)                          //地鼠坐标
	    scanf("%lf%lf",&a[i].x,&a[i].y); 	
	for(int i=1;i<=m;i++)                          //洞的坐标
	    scanf("%lf%lf",&b[i].x,&b[i].y); 		
	for(int i=1;i<=n;i++) 
	    for(int j=1;j<=m;j++) 
            {
	        if(dis(a[i].x,a[i].y,b[j].x,b[j].y)<=v*s)  //如果能进洞就在map上表示为真
		    map[i][j]=1;
	    }		  
        int ans=0;
	for(int j=1;j<=m;j++)
	{
	    memset(visit,0,sizeof(visit));
	    if(dfs(j))                                  //匈牙利算法计算最大匹配,每匹配一个地鼠就将答案加一
		ans++;  
	}		
	cout<<n-ans<<endl;                              //总数减去能活下来的地鼠即为答案
    }
    return 0;
}   

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值