希望的海洋

Ain't about how fast I get there,ain't about what's waiting on the other side

常用链接

统计

最新评论

线性DP 两次最长上升子序列 1836_POJ

题意:
n个士兵,选ct个人出队,使得重新排队得到的队伍每个人都可以向左或向右看到无穷远,没有比他高或同样高的视觉障碍(人)。求ct最小值。

分析:

要从左无障碍的看到无限远,则需有左边的人都比他低,同理,右边也一样。故找到站到中间的一个人(or two),他的两边的最长子序列之和最大。即留下的士兵最多,即出队的人最少。

使剩下的队列满足a1 < a2 < a3 ... < a(i ) <=> a(i+1) > a(i+2) > .. a(n-1) > a(n)

 

#include<cstdio>
#include
<cstdlib>
#include
<cstring>
#include
<cmath>

int d[1010],rev[1010],index[10];
double hi[1010];

int main()
{
    
int n,tmp=0,i,j,max=0,ct=0;
    
double db;
    scanf(
"%d",&n);
    
for(i=0;i<n;++i)
    
{    scanf("%lf",&hi[i]);//双精度浮点数输入须为%lf,而非%f
        d[i]=1;
        rev[i]
=1;
    }

    
//scanf("%f",&db);
    
//d[0]=1;
    for(i=1;i<n;++i)
    
{
        
for(j=0;j<i;++j)
            
if(hi[j]<hi[i]&&d[j]+1>d[i])
                d[i]
=d[j]+1;//正序以i结尾的最长上升子序列长度
    }

    
for(i=n-1;i>=0;--i)
    
{
        
for(j=n-1;j>i;--j)
            
if(hi[j]<hi[i]&&rev[i]<rev[j]+1)
                rev[i]
=rev[j]+1;//逆序以i结尾的最长上升子序列长度
    }

    
for(i=0;i<n;++i)
    
{
        
if(d[i]+rev[i]>max)//find the highest one int the middle,keep its index in record
        {
            max
=d[i]+rev[i];
            index[
0]=i;
            tmp
=0;
        }

        
else if(d[i]+rev[i]==max&&hi[i]==hi[index[0]])//&&hi[i]==hi[index[0]]漏掉则出错。此条件判断是否有两个相等的最高顶点。
        {
            index[
++tmp]=i;
        }

    }

    ct
=index[0]+1-d[index[0]]+n-1-index[tmp]+1-rev[index[tmp]];//b4 and after of 3 parts:before index[0];between o~tmp;after index[tmp]
    for(i=index[0]+1;i<index[tmp];++i)//intermediate part
        if(hi[i]<hi[index[0]])ct++;
    printf(
"%d\n",ct);
    
return 0;
}



 

posted on 2011-08-14 15:30 拥梦的小鱼 阅读(239) 评论(0)  编辑 收藏 引用 所属分类: POJ


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理