[SHOI2001]小狗散步

题目背景

Grant喜欢带着他的小狗Pandog散步。Grant以一定的速度沿着固定路线走,该路线可能自交。Pandog喜欢游览沿途的景点,不过会在给定的N个点和主人相遇。小狗和主人同时从(X1,Y1)点出发,并同时在(Xn,Yn)点汇合。小狗的速度最快是Grant的两倍。当主人从一个点以直线走向另一个点时,Pandog跑向一个它感兴趣的景点。Pandog每次与主人相遇之前最多只去一个景点。

题目描述

你现在的任务是:为Pandog寻找一条路线(有可能与主人的路线部分相同),使它能够游览最多的景点,并能够准时与主人在给定地点相遇或者汇合。

输入输出格式

输入格式:

输入文件第一行是两个整数N和M( 1≤N,M≤100 );

输入文件第二行的N个坐标给出了Grant的散步路线,即Pandog和主人相遇地点;

输入文件第三行的M个坐标给出了所有Pandog感兴趣的景点。

所有输入的坐标均不相同,且绝对值不超过1000。

输出格式:

输出小狗的移动路线。

第一行是经过的点数,第二行依次为经过的点的坐标(直角坐标系)

输入输出样例

输入样例#1:

4 5 1 4 5 7 5 2 -2 4

-4 -2 3 9 1 2 -1 3 8 -3

输出样例#1:

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

solution

这道题中的所有点显然是分成两类的,一类是小狗想走的,另一类是主人想走的,因为主人走的路是固定的,而且小狗一定要与主人在主人要走的地点相遇,而小狗的速度是主人的两倍,因此这两个点有没有边连就可以通过这个计算,显然要求小狗最多能够到的它想到的地点就是求二分图最大匹配,匈牙利算法就可以了所以这道题洛谷评价的难度过高了

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 1001;

inline int read()
{
    int f=1;
    int x=0;
    char ch;
    do
    {
        ch = getchar ();
        if(ch=='-') f=-1; 
    }while(ch<'0'||ch>'9');
    do
    {
        x=x*10+ch-'0';
        ch=getchar(); 
    }while(ch>='0'&&ch<='9');
    return f*x;
}

int n,m;
bool ma[MAXN][MAXN]={false};
bool vis[MAXN]={false};
int l[MAXN];
int ans=0;

struct node
{
    int x;
    int y;
};
node p[MAXN],d[MAXN];

inline double dis(node a,node b)
{
    return sqrt(abs(a.x-b.x)*abs(a.x-b.x)+abs(a.y-b.y)*abs(a.y-b.y));
}

inline bool dfs(int u)
{
    for(int i=1;i<=n-1;i++)
    {
        if(!vis[i]&&ma[u][i]==true)
        {
            vis[i]=true;
            if(l[i]==0||dfs(l[i]))
            {
                l[i]=u;
                return true;
            }
        }
    } 
    return false;
} 

int main()
{
    n=read();
    m=read();
    for(int i=1;i<=n;i++)
    {
        p[i].x=read();
        p[i].y=read();
    }
    for(int i=1;i<=m;i++)
    {
        d[i].x=read();
        d[i].y=read(); 
    }

    for(int i=1;i<=n-1;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(dis(p[i],p[i+1])>(dis(p[i],d[j])+dis(d[j],p[i+1]))/2)
            {
                ma[j][i]=true;
            }
        }
    }

    for(int i=1;i<=m;i++)
    {
        memset(vis,false,sizeof(vis));
        if(dfs(i)) ans++;
    }
    cout<<ans+n<<endl;
    for(int i=1;i<=n;i++)
    {
        cout<<p[i].x<<" "<<p[i].y<<" ";
        if(l[i]) cout<<d[l[i]].x<<" "<<d[l[i]].y<<" "; 
    }
} 

 

提示:

这道题没有SPJ,注意输出的顺序

转载于:https://www.cnblogs.com/wlzs1432/p/8869050.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值