• C++ 11新标准实现POJ No.2195-GoingHome


    Going Home(回家)(标签:二部图,匈牙利算法,KM算法)

    题目描述

    在网格地图上,有n个男人和n个房屋。 在每个单位时间内,每个小人都可以水平或垂直移动一个单位步长到相邻的点。 对于每个小人,您需要为他移动的每一步支付$ 1的旅行费,直到他进入房屋。 每个房子只能容纳一个小人。

    您的任务是计算您需要支付的最低金额,以便将这n个小人送入这n个不同的房子。 输入是方案图,“.”表示空白处,“ H”表示该点上的房屋,而“ m”表示该点上有一个小人。

     您可以将栅格地图上的每个点都视为一个很大的正方形,因此它可以同时容纳n个矮个子。 同样,如果一个小男人跨进带有房屋的网格而不进入该房屋也可以。

    Input

    输入中有一个或多个测试用例。 每种情况都从给出两个整数N和M的行开始,其中N是地图的行数,M是列数。 输入的其余部分将是描述地图的N行。 您可以假设N和M都在2到100之间(含2和100)。 地图上的“ H”和“ m”数量相同; 最多将有100所房屋。 N和M的输入将以0 0终止。

    Output

    对于每个测试用例,需要输出一个单个整数,这是您需要付的最小金额(以美元为单位)。

    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

    解题思路

    对于此题,看起来十分复杂,没有思路,但是如果你了解二部图以及相关算法,这个题目可以直接套模板解决。我在网络上经过了仔细的查找,发现两篇不错的博文,使用了简单易懂的例子,讲的特别清晰,如下:

    本题目需要用到的是KM算法,但是,其基础是匈牙利算法,所以,如果大家不理解匈牙利算法应该先看第一篇博文。

    上文中,讲解KM算法的那篇博文里,用的是找对象的例子,匹配原则是好感度尽可能大,此题目的匹配原则是回家的花费尽可能少,所以需要在博文中给出的算法模板中稍作修改,即可使用。

    修改的第一个地方:

    // 每个女生的初始期望值是与她相连的男生最大的好感度
        for (int i = 0; i < N; ++i) {
            ex_girl[i] = love[i][0];
            for (int j = 1; j < N; ++j) {
                ex_girl[i] = max(ex_girl[i], love[i][j]);
            }
        }
    
    ------改为------
    
    // 改为取最小值
        for (int i = 0; i < N; ++i) {
            ex_girl[i] = love[i][0];
            for (int j = 1; j < N; ++j) {
                ex_girl[i] = min(ex_girl[i], love[i][j]);
            }
        }

    修改的第二个地方:

    for (int j = 0; j < N; ++j) {
                    // 所有访问过的女生降低期望值
                    if (vis_girl[j]) ex_girl[j] -= d;
    
                    // 所有访问过的男生增加期望值
                    if (vis_boy[j]) ex_boy[j] += d;
                    // 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
                    else slack[j] -= d;
    
    ------改为------
    
    for (int j = 0; j < N; ++j) {
                    // 改为增加
                    if (vis_girl[j]) ex_girl[j] += d;
    
                    // 所有访问过的减少
                    if (vis_boy[j]) ex_boy[j] -= d;
                    // 没有访问过的增加
                    else slack[j] += d;

    经过以上两个地方的i修改,就成了求解最小期望和的模板,与此题目相适应,套一下模板即可。源代码戳下面链接即可,有完整注释~

    源代码

    ~~~Code~~~

  • 相关阅读:
    nacos启动startup.cmd一闪而过
    阿里云轻量应用服务中的linux使用
    Mapper映射文件的文件头
    vue.js:634 [Vue warn]: Cannot find element: #app7
    使用idea连接数据库时报错 Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezon
    调用本地摄像头进行拍照
    人人开源框架登录无验证码,控制台报错,验证码503 Service Unavailable
    报错:Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
    报错:com.alibaba.nacos.api.exception.NacosException: java.lang.reflect.Invocation
    报错Parameter 0 of method loadBalancerWebClientBuilderBeanPostProcessor in org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAuto
  • 原文地址:https://www.cnblogs.com/WongWai95/p/POJ-2195--WITH-CPP-11.html
Copyright © 2020-2023  润新知