`

hdu 1533 Going Home(KM算法)

    博客分类:
  • KM
阅读更多

Going Home

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1415    Accepted Submission(s): 698

Problem Description
On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every step he moves, until he enters a house. The task is complicated with the restriction that each house can accommodate only one little man. 

Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates there is a little man on that point. 

You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.
 
Input
There are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing the map. You may assume both N and M are between 2 and 100, inclusive. There will be the same number of 'H's and 'm's on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.
 
Output
For each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay. 
 
Sample Input
2 2 .m H. 5 5 HH..m ..... ..... ..... mm..H 7 8 ...H.... ...H.... ...H.... mmmHmmmm ...H.... ...H.... ...H.... 0 0
 
Sample Output
2 10 28
 

 

 

           题目大意:输入一幅图,图中有n个H和n个m分别代表有n个人和n个住所,人去住所需要花费金钱,移动一格需要一个费用,一格住所只能容纳一个人,问n个人都去到住所最低花费是多少?

求最低费用时,只要讲费用全部变成负数,然后按照原来那样求最大值,得出的结果再变成正数就是最后答案了,求最大值和最小值都是一样道理。

               赤裸裸的最大权匹配问题,先建好图,然后一个模板套上去就OK了。

代码如下:

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
using namespace std;

#define MAXN 100
#define INF 99999999

struct node
{
    int x, y;
}M[MAXN], H[MAXN];

char map[MAXN][MAXN];
int w[MAXN][MAXN];
int lx[MAXN], ly[MAXN];
bool sx[MAXN], sy[MAXN];
int pre[MAXN], slack[MAXN];
int n, m, mn, hn;

int dis(node a, node b)
{
    int dis = abs(a.x-b.x) + abs(a.y-b.y);
    return dis;
}

void bulid()
{
    int i, j;
    mn = hn = 0;
    for(i = 0; i < n; i++)
    {
        for(j = 0; j < m; j++)
        {
            cin >> map[i][j];
            if(map[i][j] == 'm')
            {
                M[mn].x = i;
                M[mn].y = j;
                mn++;
            }
            if(map[i][j] == 'H')
            {
                H[hn].x = i;
                H[hn].y = j;
                hn++;
            }
        }
    }
    memset(w, 0, sizeof(w));
    for(i = 0; i < mn; i++)
        for(j = 0; j < hn; j++)
            w[i][j] = -dis(M[i], H[j]);
}

int dfs(int u)
{
    sx[u] = true;
    for(int i = 0; i < hn; i++)
    {
        if(sy[i]) continue;
        int tp = lx[u] + ly[i] - w[u][i];
        if(!tp)
        {
            sy[i] = true;
            if(pre[i] == -1 || dfs(pre[i]))
            {
                pre[i] = u;
                return 1;
            }
        }
        else if(slack[i] > tp) slack[i] = tp;
    }
    return 0;
}

int KM()
{
    int i, j, k, d, res = 0;
    memset(pre, -1, sizeof(pre));
    memset(ly, 0, sizeof(ly));
    for(i = 0; i < mn; i++)
    {
        lx[i] = -INF;
        for(j = 0; j < hn; j++)
            lx[i] = max(lx[i], w[i][j]);
    }
    for(k = 0; k < mn; k++)
    {
        for(i = 0; i < hn; i++)
            slack[i] = INF;
        while(1)
        {
            memset(sx, false, sizeof(sx));
            memset(sy, false, sizeof(sy));
            if(dfs(k)) break;
            d = INF;
            for(i = 0; i < hn; i++)
                if(!sy[i]) d = min(d, slack[i]);
            for(i = 0; i < mn; i++)
                if(sx[i]) lx[i] -= d;
            for(i = 0; i < hn; i++)
                if(sy[i]) ly[i] += d;
        }
    }
    res = 0;
    for(i = 0; i < hn; i++)
        res += w[pre[i]][i];
    return -res;
}

int main()
{
    int ans;
    while(scanf("%d %d", &n, &m) != EOF)
    {
        if(!n && !m) break;
        bulid();
        ans = KM();
        printf("%d\n", ans);
    }

    return 0;
}
 

 

0
0
分享到:
评论

相关推荐

    hdu ACM代码 每种算法都有分类

    HDU ACM代码集合是针对ACM(国际大学生程序设计竞赛,International Collegiate Programming Contest)的一份资源,这个压缩包中的代码涵盖了多种算法,是参赛者或对算法学习感兴趣的人宝贵的参考资料。ACM竞赛旨在...

    ACM-HDU涉及了很多算法

    解决方法包括Kuhn-Munkres算法(KM算法)或匈牙利算法,它们通过增广路径来找到最大匹配。 2. **博弈**:博弈论是研究决策者之间冲突与合作的数学理论。在ACM中,博弈问题通常涉及到棋盘游戏或策略选择,如Nim游戏...

    HDU算法讲解的PPT

    HDU算法讲解的PPT是一份非常有价值的教育资源,由知名教育机构HDU(杭州电子科技大学)的lcy老师精心制作并讲解。这份PPT涵盖了算法的各个方面,是学习和提升算法能力的理想材料。标签“算法”、“讲解”和“经典”...

    二分图的完美匹配 KM算法.docx

    在给定的题目链接中,例如http://acm.hdu.edu.cn/showproblem.php?pid=1533,这些题目都是关于二分图完美匹配的应用实例,通过KM算法可以高效地找到解决方案。理解并掌握KM算法对于解决这类问题至关重要。

    hdu动态规划算法集锦

    根据提供的信息,我们可以总结出以下关于“hdu动态规划算法集锦”的知识点: ### 动态规划基础概念 动态规划是一种解决多阶段决策问题的方法,它通过将原问题分解为互相重叠的子问题,利用子问题的解来构建原问题...

    HDU 算法 ACM课件

    HDU(杭州电子科技大学)的ACM算法课件是一份宝贵的学习资源,旨在提升程序员的算法思维和解题能力。ACM,全称国际大学生程序设计竞赛(International Collegiate Programming Contest),是全球范围内的一项权威性...

    KM匹配题集

    - **【HDU 1533】Going Home**:同样是字符串匹配,可能需要求解最短的匹配长度或找出所有匹配位置。 - **【HDU 2426】Interesting Housing Problem KM**:题目可能涉及到更复杂的情况,可能需要在理解题意的基础上...

    acm课件 HDU 算法大全

    acm 技术大牛 课件 HDU 自学必备课件 全套齐全 (lecture_01)初识ACM (lecture_02)简单数学题 (lecture_03)递推求解 (lecture_04)动态规划(1)_ (lecture_05)计算几何基础_ (lecture_06)母函数 (lecture_...

    hdu1010搜索算法

    杭州电子科技大学oj平台上的第1010题,是关于搜索的题目,很不错的题

    hdu.rar_hdu

    HDU(杭州电子科技大学在线评测系统)是一个深受程序员喜爱的在线编程练习平台,它提供了丰富的算法题目供用户挑战,帮助他们提升编程技能和算法理解能力。"hdu.rar_hdu"这个压缩包文件很可能是某位程序员整理的他在...

    Dijkstra算法解HDU1874

    **Dijkstra算法解HDU1874** Dijkstra算法是一种经典的图论算法,由荷兰计算机科学家艾兹格·迪科斯彻在1956年提出,主要用于解决单源最短路径问题。在这个问题中,我们需要从一个指定的起点(源节点)出发,找到...

    HDU题目java实现

    【标题】"HDU题目java实现"所涉及的知识点主要集中在使用Java编程语言解决杭州电子科技大学(HDU)在线评测系统中的算法问题。HDU是一个知名的在线编程竞赛平台,它提供了大量的算法题目供参赛者练习和提交解决方案...

    ACM HDU题目分类

    贪心算法是一种常用的算法思想,在 ACM HDU 题目分类中,贪心算法也占据了一定的比例。例如,1009 贪心;1050 贪心;1052 贪心;1053 贪心,关于 Huffman 编码 等等。 数学题 数学题是 ACM HDU 题目分类中的一大类...

    HDU_2010.rar_hdu 2010_hdu 20_hdu acm20

    【标题】"HDU_2010.rar"是一个压缩包文件,其中包含了与"HDU 2010"相关的资源,特别是针对"HDU ACM20"比赛的编程题目。"hdu 2010"和"hdu 20"可能是该比赛的不同简称或分类,而"hdu acm20"可能指的是该赛事的第20届...

    算法-数塔(HDU-2084).rar

    标题中的“算法-数塔(HDU-2084)”是指一个编程竞赛题目,源自杭州电子科技大学(HDU)的在线编程平台。在这个问题中,参赛者被要求解决一个名为“数塔”的算法挑战。数塔问题通常涉及到递归、深度优先搜索(DFS)...

    Hdu1000—2169部分代码

    下载这些代码可以帮助学习者理解如何应用编程技巧和算法来解决HDU OJ上的问题,从而提高自己的编程和算法能力。 标签"HDu acm"进一步确认了这些代码与ACM竞赛相关的编程挑战有关,可能是参赛者或训练者为了准备比赛...

    八数码A*算法 HDU 1043

    八数码的A*算法~不是很高效,但是很适合刚刚学这个算法的朋友们

    杭电ACMhdu1163

    通过解答杭电ACMhdu1163这样的题目,参赛者可以锻炼自己的算法思维,提升编程能力,为参与更高级别的编程竞赛打下坚实基础。同时,这也是一个很好的实践平台,将理论知识转化为实际解决问题的能力。

    ACM HDU

    【标签】"ACM题解 HDU"意味着这是一个关于如何解答HDU ACM题目的资源,可能包含了解题思路、算法解析、代码实现等方面的内容。这样的资料对于准备ACM比赛的选手或者希望提升算法能力的程序员来说非常有价值。 在...

    hdu1250高精度加法

    ### hdu1250高精度加法 #### 背景介绍 在计算机科学与编程竞赛中,处理大整数运算(特别是加法、减法、乘法等)是常见的需求之一。当数字的位数超过了标准数据类型(如`int`、`long`等)所能表示的最大值时,就需要...

Global site tag (gtag.js) - Google Analytics