HDU 1025 Constructing Roads In JGShining's Kingdom(动态规划)

题目链接:Click here

题意:这道题目看了好几遍,英语是硬伤啊~~

借助了谷歌翻译~~自己修改了一下,毕竟电脑翻译的真不忍直视啊

JGShining的王国包括2n个小城市,分别位于两条平行线。
这些城市中有一半都含有丰富的资源(我们称他们丰富的城市),而另一些缺少资源(我们称他们为穷人市)。每个贫困城市缺少一种资源,每一个富有城市富有一种资源。你可以假设没有任何两个城市同时缺少一个同类型的资源,并没有两个城市富含一个同类型的资源。
随着工业的发展,贫困城市想从那些富有城市购买资源。存在的道路很小小,他们无法保证重型卡车通过,所以要建设新的道路。贫穷的城市强烈BS对方,富有的也是。贫穷的城市不想建立与其他穷国的道路,富有的城市也无法忍受与其他富国共享道路的尽头。
由于经济利益的,任何丰富的城市会愿意出口资源对任何一个贫穷城市。标志着从1到n丰富黎平位于I线和穷国标志着从1到n位于二号线。富城1的位置是在所有其他城市的左边,富城2是所有其他城市不包括丰富的城市1的左边,富城3是富城1和富城2的权利,但在左边所有其他城市的...等为穷国。
但你也知道,两个交叉的道路可能会造成大量交通事故,所以JGShining已经建立了一个法律,禁止修建道路交叉。
为了建造更多的路,王国的年轻英俊的国王 - JGShining需要你的帮助,请帮他。 ^ _ ^

思路:看了一些解题报告,说是关于最长上升子序列的问题,但我感觉虽然有些关系,其实主要的还是贪心吧,个人意见。
参考了网上很多代码,现在借用一个大神的思路和数据做下解释:
假设要寻找序列是a[n]

(1)当遍历到数组a的第一个元素的时候,就将这个元素放入到dp数组中,以后遍历到的元素都和已经放入到dp数组中的元素进行比较;

(2)如果比dp数组中的每个元素都大,则将该元素插入到dp数组的最后一个元素,并且dp数组的长度要加1;

(3)如果比b数组中最后一个元素小,就要运用二分法进行查找,查找出第一个比该元素大的最小的元素,然后将其替换。

这是数据
假设上面是富有城市a,下面是贫困城市b。
第一步:
这里写图片描述
a1与b5之间建设道路
a2与b9之间建设道路
第二步:
这里写图片描述
因为与a3相连的城市号比a1与a2的都要小,所以a1与b5 a2与b9之间断开。只留下a3与b4
此时dp[2]还是9,这个参照程序就知道为什么
第三步,第四步:
这里写图片描述
a4与b1,a5与b3,a7与b6,a8与b7
看图应该能够理解吧~~
这时,答案就是dp的下标,4

具体看代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cstdlib>

using namespace std;

int dp[500003], city[500003];

int main()
{
    int n, cout, a, b, ans, left, right, mid;
    cout= 1;
    while(scanf("%d", &n) != EOF)
    {
        ans = 1;
        for(int i = 0; i < n; i++)
        {
            scanf("%d%d", &a, &b);
            city[a] = b; //富有城市要建立连接的贫穷城市的标号
        }
        dp[1] = city[1];
        for(int i = 2; i <= n; i++)
        {
            left = 0;
            right = ans;
            while(left <= right)
            {//二分法查找
                mid = (left + right) / 2;
                if(city[i] > dp[mid])
                    left = mid + 1;
                else
                    right = mid - 1;
            }
            dp[left] = city[i];  //替换该标号
            if(left > ans)  //如果找不到,证明标号比dp中所有的都大,则插到数组末尾
                ans++;
        }
        printf("Case %d:\n", cout);
        if(ans == 1)//注意道路的单复数问题
            printf("My king, at most 1 road can be built.\n\n");
        else
            printf("My king, at most %d roads can be built.\n\n", ans);
        cout++;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值