题意:Bob和他的狗一起溜达,狗移动的速度是Bob的2倍。先给出Bob行走路线上的一些点,
每次Bob从(x,y)走时狗可以离开他去玩耍或观赏一些景点,但要保证在Bob到达(x+1,y+1)时狗也达到了(x+1,y+1);
同时给出了一些景点的坐标。求小狗狗最多可以经过多少的已给的点(即Bob路线上的所有点+小狗走的景点),并把
小狗狗的行走路线打印出来
思路:简单的二分图求最大匹配问题,根据景点到(x,y)和(x+1,y+1)距离之和与(x,y)和(x+1,y+1)之间距离的2倍
关系建图,然后求解最大匹配即可
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int MAX=110;
int n,m;
typedef struct node
{
int x;
int y;
} Node;
Node bob[MAX];
Node dog[MAX];
int g[MAX][MAX];
double getdis(Node a,Node b)
{
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int linker[MAX];
int save[MAX];
int used[MAX];
bool dfs(int u)
{
for(int v=0; v<m; v++)
{
if(g[u][v]&&!used[v])
{
used[v]=true;
if(linker[v]==-1||dfs(linker[v]))
{
linker[v]=u;
return true;
}
}
}
return false;
}
int hungary()
{
int res=0;
memset(linker,-1,sizeof(linker));
for(int u=0; u<n-1; u++)
{
memset(used,false,sizeof(used));
if(dfs(u)) res++;
}
return res;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
scanf("%d%d",&bob[i].x,&bob[i].y);
for(int i=0; i<m; i++)
scanf("%d%d",&dog[i].x,&dog[i].y);
memset(g,0,sizeof(g));
for(int i=0; i<n-1; i++)
for(int k=0; k<m; k++)
{
double a=getdis(bob[i],bob[i+1]);
double b=getdis(bob[i],dog[k]);
double c=getdis(bob[i+1],dog[k]);
if(b+c-a-a<10e-8)
g[i][k]=1;
}
printf("%d\n",hungary()+n);
memset(save,-1,sizeof(save));
for(int i=0; i<m; i++)
{
if(linker[i]!=-1)
save[linker[i]]=i;
}
for(int i=0; i<n-1; i++)
{
printf("%d %d ",bob[i].x,bob[i].y);
if(save[i]!=-1)
printf("%d %d ",dog[save[i]].x,dog[save[i]].y);
}
printf("%d %d\n",bob[n-1].x,bob[n-1].y);
if(T>0)
printf("\n");
}
return 0;
}