一个n*m个grid上面有x个man和x个house,现在就是man每移动一步就需要花费1元,现在就是x个人要找房子呆着,且一个房子只能容纳一个人,求所有人找到呆着的房子的最小花费。
建立一个超级源点s和汇点t,s到每个人建立一条容量为1、费用为0的边,每个人到每个房子建立一条容量为inf、费用为两者间的最小距离,方向变的费用为负,房子到t建立一条容量为1、费用为0的边。。。
/***************************************** Author :Crazy_AC(JamesQi) Time :2015 File Name : *****************************************/ // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; typedef pair<ii,int> iii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 110; int cap[maxn*2][maxn*2], pre[maxn*2], cost[maxn*2][maxn*2]; vector<ii> men,house; int s, t; char str[maxn]; int n, m; int num; bool vis[maxn*2]; int dis[maxn*2]; bool spfa() { queue<int> que; memset(dis, INF,sizeof dis); memset(vis, false,sizeof vis); memset(pre, -1,sizeof pre); dis[s] = 0,vis[s] = true; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); vis[u] = false; for (int v = s;v <= t;++v) { if (cap[u][v] > 0 && dis[v] > dis[u] + cost[u][v]) { dis[v] = dis[u] + cost[u][v]; pre[v] = u; if (!vis[v]) { vis[v] = true; que.push(v); } } } } return pre[t] != -1; } int MCMF() { int ret = 0; while(spfa()) { for (int v = t;v != s;v = pre[v]) { cap[pre[v]][v] -= 1; cap[v][pre[v]] += 1; } ret += dis[t]; } return ret; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); while(scanf("%d%d",&n,&m)) { if (n==0&&m==0) break; men.clear(),house.clear(); for (int i = 1;i <= n;++i) { scanf("%s",str+1); for (int j = 1;j <= m;++j) { if (str[j] == 'H') house.push_back(ii(i, j)); if (str[j] == 'm') men.push_back(ii(i, j)); } } memset(cap, 0,sizeof cap); memset(cost, 0,sizeof cost); num = (int)men.size(); s = 0, t = num*2+1; for (int i = 0;i < num;++i) { int u = i + 1; cap[s][u] = 1; for (int j = 0;j < num;++j) { int dis = abs(men[i].first - house[j].first) + abs(men[i].second - house[j].second); int v = j + 1 + num; cap[v][t] = 1; cap[u][v] = INF; cost[u][v] = dis; cost[v][u] = -dis; } } printf("%d\n", MCMF()); } return 0; }
/***************************************** Author :Crazy_AC(JamesQi) Time :2016 File Name : *****************************************/ // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; typedef pair<ii,int> iii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 110; struct Point{ int x,y; Point(){} Point(int x,int y):x(x),y(y){} int operator - (const Point& rhs) { return abs(x - rhs.x) + abs(y - rhs.y); } }A[maxn],B[maxn]; int cnt1,cnt2; int n, m; char str[maxn]; int head[maxn*2],cap[maxn*maxn*2],flow[maxn*maxn*2],nxt[maxn*maxn*2],cost[maxn*maxn*2],pnt[maxn*maxn*2]; int pre[maxn*2]; int ecnt; int s, t; inline void addedge(int u,int v,int c,int w) { cap[ecnt] = c, flow[ecnt] = 0,cost[ecnt] = w,pnt[ecnt] = v; nxt[ecnt] = head[u],head[u] = ecnt++; cap[ecnt] = 0,flow[ecnt] = 0,cost[ecnt] = -w,pnt[ecnt] = u; nxt[ecnt] = head[v],head[v] = ecnt++; } int dis[maxn*2]; bool vis[maxn*2]; bool spfa() { queue<int> que; memset(pre, -1,sizeof pre); memset(dis, INF,sizeof dis); memset(vis, false,sizeof vis); que.push(s); vis[s] = true; dis[s] = 0; while(!que.empty()) { int u = que.front(); que.pop(); vis[u] = false; for (int i = head[u];i != -1;i = nxt[i]) { int v = pnt[i]; if (cap[i] > flow[i] && dis[v] > dis[u] + cost[i]) { dis[v] = dis[u] + cost[i]; pre[v] = i; if (!vis[v]) { vis[v] = true; que.push(v); } } } } return dis[t] != INF; } int MCMF() { int ret = 0; while(spfa()) { int minflow = INF; for (int v = t;v != s;v = pnt[pre[v]^1]) { int i = pre[v]; minflow = min(minflow, cap[i] - flow[i]); } ret += minflow * dis[t]; for (int v = t;v != s;v = pnt[pre[v]^1]) { int i = pre[v]; flow[i] += minflow; flow[i^1] -= minflow; if (pre[v]==-1)break; } } return ret; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); while(scanf("%d%d",&n,&m)) { if (n==0&&m==0)break; cnt1 = cnt2 = 0; for (int i = 1;i <= n;++i) { scanf("%s",str+1); for (int j = 1;j <= m;++j) { if (str[j] == 'H') A[++cnt1] = Point(i, j); if (str[j] == 'm') B[++cnt2] = Point(i, j); } } s = 0,t = 2*cnt1+1; memset(head, -1,sizeof head); ecnt = 0; for (int i = 1;i <= cnt1;++i) {//cnt1 == cnt2; addedge(s, i, 1, 0); addedge(i+cnt1, t, 1, 0); for (int j = 1;j <= cnt2;++j) { int dis = A[i] - B[j]; addedge(i,j+cnt1,INF,dis); } } printf("%d\n", MCMF()); } return 0; }