• poj2195


    题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少。

    分析:最小费用最大流每个人一个点,每个房子一个点,每个人到所有房子加容量为1费用为二者距离的边,源到所有人加容量为1费用为0的边,所有房子到汇加容量为1费用为0的边。因为没有初始化ne,wa了两次。渐渐开始理解网络流的题型了,是一种可以自由分配,求最优分配方案的题。

    View Code
    #include <iostream>
    #include
    <cstdlib>
    #include
    <cstring>
    #include
    <cstdio>
    #include
    <cmath>
    usingnamespace std;

    #define inf 0x3f3f3f3f
    #define N 205
    #define E 40000

    struct XPoint
    {
    int x, y;
    }house[N], man[N];

    int n, m;
    int hcount, mcount;

    struct network
    {
    int nv, ne, pnt[E], nxt[E];
    int vis[N], que[N], head[N], pv[N], pe[N];
    int flow, cap[E];
    int cost, dis[E], d[N];
    int src, sink;
    void addedge(int u, int v, int c, int w)
    {
    pnt[ne]
    = v;
    cap[ne]
    = c;
    dis[ne]
    =+w;
    nxt[ne]
    = head[u];
    head[u]
    = (ne++);
    pnt[ne]
    = u;
    cap[ne]
    =0;
    dis[ne]
    =-w;
    nxt[ne]
    = head[v];
    head[v]
    = (ne++);
    }
    int mincost()
    {
    int i, k, f, r;
    int mxf;
    for (flow =0, cost =0;;)
    {
    memset(pv,
    -1, sizeof(pv));
    memset(vis,
    0, sizeof(vis));
    for (i =0; i < nv; ++i)
    d[i]
    = inf;
    d[src]
    =0;
    pv[src]
    = src;
    vis[src]
    =1;

    for (f =0, r =1, que[0] = src; r != f;)
    {
    i
    = que[f++];
    vis[i]
    =0;
    if (N == f)
    f
    =0;
    for (k = head[i]; k !=-1; k = nxt[k])
    if (cap[k] && dis[k] + d[i] < d[pnt[k]])
    {
    d[pnt[k]]
    = dis[k] + d[i];
    if (0== vis[pnt[k]])
    {
    vis[pnt[k]]
    =1;
    que[r
    ++] = pnt[k];
    if (N == r)
    r
    =0;
    }
    pv[pnt[k]]
    = i;
    pe[pnt[k]]
    = k;
    }
    }
    if (-1== pv[sink])
    break;
    for (k = sink, mxf = inf; k != src; k = pv[k])
    if (cap[pe[k]] < mxf)
    mxf
    = cap[pe[k]];
    flow
    += mxf;
    cost
    += d[sink] * mxf;
    for (k = sink; k != src; k = pv[k])
    {
    cap[pe[k]]
    -= mxf;
    cap[pe[k]
    ^1] += mxf;
    }
    }
    return cost;
    }
    void build()
    {
    hcount
    = mcount =0;
    for (int i =0; i < n; i++)
    {
    for (int j =0; j < m; j++)
    {
    char ch = getchar();
    if (ch =='H')
    {
    house[hcount].x
    = i;
    house[hcount].y
    = j;
    hcount
    ++;
    }
    if (ch =='m')
    {
    man[mcount].x
    = i;
    man[mcount].y
    = j;
    mcount
    ++;
    }
    }
    getchar();
    }
    nv
    = hcount *2+2;
    ne
    =0;
    memset(head,
    -1, sizeof(head));
    for (int i =0; i < mcount; i++)
    for (int j =0; j < hcount; j++)
    addedge(i, j
    + mcount, 1, abs(man[i].x - house[j].x) + abs(man[i].y - house[j].y));
    src
    = nv -2;
    sink
    = nv -1;
    for (int i =0; i < mcount; i++)
    addedge(src, i,
    1, 0);
    for (int i =0; i < hcount; i++)
    addedge(i
    + mcount, sink, 1, 0);
    }
    }g;

    int main()
    {
    //freopen("t.txt", "r", stdin);
    while (scanf("%d%d", &n, &m), n | m)
    {
    getchar();
    g.build();
    int ans = g.mincost();
    printf(
    "%d\n", ans);
    }
    return0;
    }
  • 相关阅读:
    ubuntu18.04安装ssh服务
    跳转
    【WinForm】—窗体之间传值的几种方式
    使用jQuery完成复选框的全选和全不选
    VS2015下载安装随笔记录
    关于c#数据类型,类型转换,变量,常量,转义符。
    浅谈表单同步提交和异步提交
    form表单提交和跳转
    2019年8月19日矩阵
    C# WinForm快捷键设置技巧
  • 原文地址:https://www.cnblogs.com/rainydays/p/2073224.html
Copyright © 2020-2023  润新知