题目的意思是,两行城市,从左到右为1,2,3……n个城市。上面的下面的城市要与上面某个的城市相连,在不出现相交的情况下,最多可以连多少条。
知道了题意,就知道了应该用DP来做。
这一题,数据量比较大,用普通的DP,时间复杂度为N^2,会超时,我们应该用另一种DP方法,时间复杂度为nlogn。
nlogn的DP的思路大概就是给你一个数,插到一个数组中,该位置已存在,就覆盖它。也就是可以用二分查找提高效率。
注意:输出的时候,要注意英语的单复数!!~~
下面的是AC的代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n, dp[500005], a[500005];
int finds(int num, int len) //二分查找num的位置并返回
{
int left, right, mid;
left = 1; right = len;
mid = (left + right) / 2;
while(left <= right)
{
if(dp[mid] == num)
return mid;
else if(dp[mid] < num)
left = mid + 1;
else
right = mid - 1;
mid = (left + right) / 2;
}
return left;
}
int main()
{
int i, j, k, count = 0;
while(scanf("%d", &n) != EOF)
{
for(i = 0; i < n; i++) //输入poor城市对应的rich城市
{
scanf("%d%d", &j, &k);
a[j] = k; //a数组为第j个poor城市对应第k个rich城市
}
memset(dp, 0, sizeof(dp));
dp[1] = a[1]; //插入一个数
int len = 1; //数组长度为1
for(i = 2; i <= n; i++)
{
j = finds(a[i], len); //查找剩下的poor城市对应的rich城市在数组的位置
dp[j] = a[i]; //覆盖
if(len < j) //更新长度
{
len = j;
}
}
printf("Case %d:\n", ++count); //输出
if(len == 1)
printf("My king, at most %d road can be built.\n", len);
else
printf("My king, at most %d roads can be built.\n", len);
printf("\n");
}
return 0;
}