您的位置:首页 > 编程语言 > Go语言

poj2195_GoingHome【最小费用最大流】

2015-06-02 19:19 274 查看
这道题的题意是:在一个矩阵空间中,分布着m个人和m个房子,每个房子中要安排一个人,每个人移动一步需要1美元,求为每个人安排房子后所需要的金钱的最小值。
//建立一个原点s,链接人,人和每个房子都要建边,费用为,abs(x人-x房子)+abs(y人-y房子)。
//每个房子链接一个汇点T。
//套用最小费用最大流即可。
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <queue>
#define Maxsize 240
using namespace std;
struct loc{
int x,y;
}due[Maxsize];
struct Edge{
int to,cap,cost,rev;
};
vector<Edge> g[Maxsize];
queue<int> que;
char ch[Maxsize][Maxsize];
int dist[Maxsize];
int prev[Maxsize];
int pree[Maxsize];
bool inque[Maxsize];
int n,m;
int sh,sm;
int T;
void add_edge(int from,int to,int cap,int cost)
{
g[from].push_back((Edge){to,cap,cost,g[to].size()});
g[to].push_back((Edge){from,0,-cost,g[from].size()-1});
}
int abs(int x)
{
if(x>0)
return x;
return -x;
}
void init()
{
int i;
sh=0;sm=0;
for(i=0;i<Maxsize;i++)
g[i].clear();
}
void scanf_map()
{
int i,j,k;
for(i=0;i<n;i++)
{
gets(ch[i]);
for(j=0;j<m;j++)
{
if(ch[i][j]=='H')
{
sh++;
due[sh].x=i;
due[sh].y=j;
add_edge(0,sh,1,0);
}
}
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(ch[i][j]=='m')
{
sm++;
for(k=1;k<=sh;k++)
{
add_edge(k,sh+sm,1,abs(due[k].x-i)+abs(due[k].y-j));
}
}
}
}
T=sh+sm+1;
for(i=sh+1;i<T;i++)
{
add_edge(i,T,1,0);
}
}
int FindMinCostFlow()
{
int res=0;
int u,v;
int f=sh>sm?sm:sh;
while(f>0)
{
//spfa算法求最短路,并记录路径
memset(dist,0x3f,sizeof(dist));
memset(inque,0,sizeof(inque));
dist[0]=0;
inque[0]=1;
que.push(0);
while(!que.empty())
{
u=que.front();que.pop();inque[u]=0;
for(v=0;v<g[u].size();v++)
{
Edge &e=g[u][v];
if(e.cap>0&&dist[e.to]>dist[u]+e.cost)
{
dist[e.to]=dist[u]+e.cost;
prev[e.to]=u;
pree[e.to]=v;
if(!inque[e.to])
{
que.push(e.to);
inque[e.to]=1;
}
}
}

}
//更改路径流量
for(v=T;v!=0;v=prev[v])
{
Edge &e=g[prev[v]][pree[v]];
e.cap-=1;
g[e.to][e.rev].cap+=1;
}
f-=1;
res+=dist[T];
}
return res;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
getchar();
if(n==0&&m==0)
break;
init();
scanf_map();
printf("%d\n",FindMinCostFlow());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: