标签:integer image hold ima iss lin add single 价格

2 2 .m H. 5 5 HH..m ..... ..... ..... mm..H 7 8 ...H.... ...H.... ...H.... mmmHmmmm ...H.... ...H.... ...H.... 0 0
2 10 28
题意:给一个地图,标了人m和房H的位置,人数和房子数量相等,如今全部人要回各自的家,一个房仅仅能容一个人。问全部人走的步数总和最少是多少?每一步仅仅能走相邻的格子。
解题:最小费用流。
分3类点:1:源点S,汇点T。
2:人M。
3:房H。
建图:(u , v , cap, cost):u-->v边容为cap。花费为cost
1):(S , M , 1 , 0)
2):(M , H , 1 , mindis):mindis表示人到房的最短距离
3:(H , T , 1 , 0)
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int MAXN = 10010;
const int MAXM = 100100;
const int INF = 1<<30;
struct EDG{
int to,next,cap,flow;
int cost; //单位价格
}edg[MAXM];
int head[MAXN],eid;
int pre[MAXN], cost[MAXN] ; //点0~(n-1)
void init(){
eid=0;
memset(head,-1,sizeof(head));
}
void addEdg(int u,int v,int cap,int cst){
edg[eid].to=v; edg[eid].next=head[u]; edg[eid].cost = cst;
edg[eid].cap=cap; edg[eid].flow=0; head[u]=eid++;
edg[eid].to=u; edg[eid].next=head[v]; edg[eid].cost = -cst;
edg[eid].cap=0; edg[eid].flow=0; head[v]=eid++;
}
bool inq[MAXN];
bool spfa(int sNode,int eNode,int n){
queue<int>q;
for(int i=0; i<n; i++){
inq[i]=false; cost[i]= INF;
}
cost[sNode]=0; inq[sNode]=1; pre[sNode]=-1;
q.push(sNode);
while(!q.empty()){
int u=q.front(); q.pop();
inq[u]=0;
for(int i=head[u]; i!=-1; i=edg[i].next){
int v=edg[i].to;
if(edg[i].cap-edg[i].flow>0 && cost[v]>cost[u]+edg[i].cost){ //在满足可增流的情况下,最小花费
cost[v] = cost[u]+edg[i].cost;
pre[v]=i; //记录路径上的边
if(!inq[v])
q.push(v),inq[v]=1;
}
}
}
return cost[eNode]!=INF; //推断有没有增广路
}
//反回的是最大流,最小花费为minCost
int minCost_maxFlow(int sNode,int eNode ,int& minCost,int n){
int ans=0;
while(spfa(sNode,eNode,n)){
int mint=INF;
for(int i=pre[eNode]; i!=-1; i=pre[edg[i^1].to]){
if(mint>edg[i].cap-edg[i].flow)
mint=edg[i].cap-edg[i].flow;
}
ans+=mint;
for(int i=pre[eNode]; i!=-1; i=pre[edg[i^1].to]){
edg[i].flow+=mint; edg[i^1].flow-=mint;
minCost+=mint*edg[i].cost;
}
}
return ans;
}
int abs(int a){ return a>0?a:-a; }
int buildGraph(char mapt[105][105],int n,int m){
int id[105][105] , k=1 ;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
if(mapt[i][j]=='H'||mapt[i][j]=='m')
id[i][j]=k++;
int s=0 , t = k;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
if(mapt[i][j]=='m'){
int u,v;
u=id[i][j];
addEdg(s,u,1,0);
for(int ti=0; ti<n; ti++)
for(int tj=0; tj<m; tj++)
if(mapt[ti][tj]=='H'){
v=id[ti][tj];
addEdg(u,v,1,abs(ti-i)+abs(tj-j));
}
}
else if(mapt[i][j]=='H')
addEdg(id[i][j],t,1,0);
return k;
}
int main(){
int n,m;
char mapt[105][105];
while(scanf("%d%d",&n,&m)>0&&(n||m)){
for(int i=0; i<n; i++)
scanf("%s",mapt[i]);
init();
int s=0,t=buildGraph(mapt,n,m) , minCost=0;
minCost_maxFlow(s,t,minCost,t+1);
printf("%d\n",minCost);
}
}
标签:integer image hold ima iss lin add single 价格
原文地址:http://www.cnblogs.com/jhcelue/p/7029026.html