题目内容:
Half of these cities are rich in resource (we call them rich cities) while the others are short of resource (we call them poor cities). Each poor city is short of exactly one kind of resource and also each rich city is rich in exactly one kind of resource. You may assume no two poor cities are short of one same kind of resource and no two rich cities are rich in one same kind of resource.
With the development of industry, poor cities wanna import resource from rich ones. The roads existed are so small that they're unable to ensure the heavy trucks, so new roads should be built. The poor cities strongly BS each other, so are the rich ones. Poor cities don't wanna build a road with other poor ones, and rich ones also can't abide sharing an end of road with other rich ones. Because of economic benefit, any rich city will be willing to export resource to any poor one.
Rich citis marked from 1 to n are located in Line I and poor ones marked from 1 to n are located in Line II.
The location of Rich City 1 is on the left of all other cities, Rich City 2 is on the left of all other cities excluding Rich City 1, Rich City 3 is on the right of Rich City 1 and Rich City 2 but on the left of all other cities ... And so as the poor ones.
But as you know, two crossed roads may cause a lot of traffic accident so JGShining has established a law to forbid constructing crossed roads.
For example, the roads in Figure I are forbidden.
![](https://i-blog.csdnimg.cn/blog_migrate/1b6d9fcf6bd94b098baf0168f377fdc6.png)
In order to build as many roads as possible, the young and handsome king of the kingdom - JGShining needs your help, please help him. ^_^
You should tell JGShining what's the maximal number of road(s) can be built.
2 1 2 2 1 3 1 2 2 3 3 1
Case 1: My king, at most 1 road can be built. Case 2: My king, at most 2 roads can be built.HintHuge input, scanf is recommended.
有两条公路上面分别有两种不同的城市,现在要根据输入数据修建道路来连接城市(所连接的城市不属于在同一条开始时的公路上),同时修建的道路的不能够交叉,求能修建的道路最大数量
题目分析:
这道题表面看比较复杂,我在做这道题时候一开始也把题意考虑复杂了,但后来发现题中虽未说明但是默认的一个城市只会修一条道路,而不会出现1、2,1、3,1、4等等一条城市出发有多条道路的情况,因而题目的难度大大简化了,将输入数据按照出发城市递增顺序排序后题目转换成了常见的最长上升子序列问题,但这道题真正的难点就正在于此,OJ对于算法的时间复杂都要求是至少要nlgn,因而常规dp的n²无疑无法通过,在这里介绍一种新的子序列算法;
假定给定的子序列为2,1,5,6,4,3,7,9,8
在这里定义一个新的数组dp[ ],注意length数组的值代表并不是子序列各项的值,而是在当前长度下所能取到的最小末尾
算法开始:
首先第一项2,将其放入dp[1]中,即此时当dp长度为1时序列最后一个数为2
下一项,因为1小于2,所以此时dp[1]的值被替换为1
下一项,因为5大于1,所以此时应有dp[2]=5
下一项,此时有dp[3]=6
下一项,因为4的值介于1和5之间,所以此时更新为dp[2]=4
以此类推
下一项,dp[2]=3
下一项,dp[4]=7
下一项,dp[5]=9
下一项,dp[5]=8
所以最终得到的dp数组为1,3,6,7,8,分别代表最长子序列长度为1至5时序列末尾数的值,注意若要求出各个长度子序列的具体项,只需要根据已求出末尾数遍历一遍即可
不难发现,在此种算法下,真正的时间开销在于寻找合适的将数据插入数组中的位置,此时配合二分法查找即可将查找时间优化到lgn,再乘以一次遍历的时间得到nlgn的算法
题目代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef struct
{
int begin;
int end;
}city;
city cities[500005];
int dp[500005];
int cmp(city x,city y)
{
return x.begin<y.begin;
}
int search(int node,int q)
{
int p=0;
int mid;
while(p<q)
{
mid=(p+q)/2;
if(node>dp[mid])
p=mid+1;
else
q=mid;
}
mid=q;
return mid;
}
int main()
{
int order=0;
int n;
while(scanf("%d",&n)!=EOF)
{
order++;
for(int i=0;i<n;i++)
scanf("%d%d",&cities[i].begin,&cities[i].end);
memset(dp,0,sizeof(dp));
sort(cities,cities+n,cmp);
int lebel=0;
dp[lebel]=cities[0].end;
for(int i=0;i<n;i++)
{
if(cities[i].end>dp[lebel])
dp[++lebel]=cities[i].end;
else
{
int t=search(cities[i].end,lebel);
dp[t]=cities[i].end;
}
}
if(lebel==0)printf("Case %d:\nMy king, at most %d road can be built.\n\n",order,lebel+1);
else printf("Case %d:\nMy king, at most %d roads can be built.\n\n",order,lebel+1);
}
return 0;
}
解题评价:
这道题正如我在题目分析中所说的单城市单道路的题意大大降低了难度,其真正的价值是nlgn的最长子序列上升算法
当前水平评分:5