The main idea: in a grid there are n small men and N houses, now want to let every little man have a house to live, but everyone to move a bit to spend ¥1, now find out the minimum total cost. PS: It can be thought that each point of the grid is a large square and accommodates all the people who can walk at the point of having a house but do not enter the house.
Analysis: Man-house, very perfect with all minimum values match Ah, the cost of people to a house is their Manhattan distance between them, using these distances to construct a binary graph, and then use the KM algorithm to find the minimum fee.
here is the KM algorithm
*********************************************************************************************************** ************************************************************************#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
#include <math.h>
usingnamespaceStd
ConstintMAXN =107;
ConstintOO = 1e9+7;
structpoint{intx, y;} MAN[MAXN], HOUSE[MAXN];
CharG[MAXN][MAXN];
intW[MAXN][MAXN], SLACK[MAXN], Nx, Ny;
intDX[MAXN], DY[MAXN], LY[MAXN];
BOOLVX[MAXN], VY[MAXN];
voidInIt ()
{
Nx = Ny =0;
for(intI=1; i<maxn; i++)
{
Dx[i] =-oo;
Dy[i] =0;
}
}
BOOLFind (intI
{
Vx[i] =true;
for(intj=1; j<=ny; J + +)
{
if(!vy[j] && w[i][j] = = Dx[i]+dy[j])
{
VY[J] =true;
if(! LY[J] | | Find (Ly[j]))
{
LY[J] = i;
returntrue;
}
}
Elseif(!vy[j])
Slack[j] = min (Slack[j], dx[i]+dy[j]-w[i][j]);
}
returnfalse;
}
intKM ()
{
intI, J;
memset (Ly,0,sizeof(Ly));
for(i=1; i<=nx; i++)
{
for(j=1; j<=ny; J + +)
SLACK[J] = oo;
while(true)
{
memset (VX,false,sizeof(VX));
memset (VY,false,sizeof(VY));
if(Find (i) = =true)
Break;
intD = oo;
for(j=1; j<=ny; J + +)
{
if(!vy[j] && d > slack[j])
d = slack[j];
}
for(j=1; j<=nx; J + +)
{
if(Vx[j])
DX[J]-= D;
}
for(j=1; j<=ny; J + +)
{
if(Vy[j])
DY[J] + = D;
Else
SLACK[J]-= D;
}
}
}
intsum =0;
for(i=1; i<=ny; i++)
Sum + = W[ly[i]][i];
return-sum;
}
intMain ()
{
intM, N;
while(SCANF ("%d%d", &m, &n), m+n)
{
intI, J;
InIt ();
for(i=0; i<m; i++)
scanf"%s", G[i]);
for(i=0; i<m; i++)
for(j=0; j<n; J + +)
{
if(G[i][j] = ='m')
{
nx++;
man[nx].x = i;
Man[nx].y = j;
}
if(G[i][j] = ='H')
{
ny++;
house[ny].x = i;
House[ny].y = j;
}
}
for(i=1; i<=nx; i++)
for(j=1; j<=ny; J + +)
{
W[I][J] = fabs (man[i].x-house[j].x) + fabs (MAN[I].Y-HOUSE[J].Y);
W[I][J] =-w[i][j];
Dx[i] = max (Dx[i], w[i][j]);
}
printf"%d\n", KM ());
}
return0;
}View Code
Going HOME-POJ 2195 (Network Flow | Two-point matching)