这是改进前的算法,算法复杂度是n^2
2. #include <stdio.h>
3. #define MAX 1000
4. int seq[MAX+10];
5. int seqlen[MAX+10];
6. int main()
7. {
8. int i,j,k,N,max,maxlen=1;
9. for(i=1;i<=9;i++)
10. seqlen[i]=1; //seqlen数组存以第i个数为终点的最长上升序列
11. scanf("%d",&N);
12. for(i=1;i<=N;i++)
13. scanf("%d",&seq[i]); //seq数组保存序列数组
14. for (i=2;i<=N;i++)
15. {
16. max=0;
17. for (j=1;j<=i-1;j++)
18. {
19. if(seq[j]<seq[i]&&seqlen[j]>max) //在前i-1个序列中,寻找以终点小于seq[i]的最长的子序列,即最优子状态
20. max=seqlen[j];
21. }
22. seqlen[i]=max+1;
23. if(seqlen[i]>maxlen) //seqlen中保存的是第i个数为终点的最长上升序列,找出这个数组中最大的值即为最优序列长度
24. maxlen=seqlen[i];
25. }
26. printf("%d/n",maxlen);
27. return 0;
28. }
改进后的算法:
#include <stdio.h>
int city[500005];
int dp[500005];
int binaryseach(int x,int len)
{
int left,mid,right;
left=1;
right=len;
while(left<=right)
{
mid=(right+left)/2;
if(dp[mid]<x)
{
left=mid+1;
}
else
{
right=mid-1;
}
}
return left;
}
int main()
{
int i,j;
int len;
int r,p;
int n;
int casen;
casen=0;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d%d",&r,&p);
city[r]=p;
}
dp[0]=-1000000;
dp[1]=city[1];
len=1;
for(i=2;i<=n;i++)
{
j=binaryseach(city[i],len);
dp[j]=city[i];
if(j>len)
{
len=j;
}
}
if(len==1)
{
printf("Case %d:\nMy king, at most 1 road can be built.\n\n",++casen);
}
else
{
printf("Case %d:\nMy king, at most %d roads can be built.\n\n",++casen,len);
}
}
return 0;
}
关于优化的思想:
二分查找会动态的更新dp[len]中的数据,二分搜索会在dp[len]中查找city[i]的位置然后替换掉原来的数据。如果不在dp[len]中,那么j就会比len大,所以len++;