现在的位置: 首页 > 综合 > 正文

HWOJ 合唱队

2015年01月15日 ⁄ 综合 ⁄ 共 1097字 ⁄ 字号 评论关闭

HWOJ 合唱队

题目:合唱队

Alt text

样例输入:
8
186 186 150 200 160 130 197 200
样例输出:
4
题目分析:
算法思路:

①动态规划求出以每个人结尾的左边和右边的最大队列长度
②枚举每个人为“中心点”,计算出满足题目要求的队列长度,记录最大值
③用left[i]表示从左边起到第i个人结束的最长上升队列的人数,那么得到最优解的结构:left[i],用right[i]表示从右边起到第i个人结束的最大上升队列的人数,得到:right[i]
④初始化left[i] = 1通过内循环更新lefe[i],right[i]也一样
⑤最后循环求出最大的合唱队列
⑥循环 第一个左边:i = 1 i < n j = 0 j < i 右边 i = n-2 i >=0 j = n-1 j > i
学习笔记:
学会动态分析,找出最优解

===============================================================================
参考代码:

//合唱对.c
//2014.7.5
#include <stdio.h>
#include <string.h>
#define maxn 100+5

//a[i]表示第i个人的身高,left[i]表示从左边第一个到a[i]个最长上升序列,right[i]表示从右边第一个到a[i]的最长上升子序列
int a[maxn];
int left[maxn];  
int right[maxn];

int main()
{
    int i,j,n,max,cnt = 0;
    while(scanf("%d",&n) != EOF)
    {
        for(i = 0; i < n;i++)
        {
            scanf("%d",&a[i]);
        }

        //初始化全部设为0
        memset(left, 0, sizeof(left));
        memset(right, 0, sizeof(right));

        //左侧的最长上升子序列
        left[0] = 1;
        for(i = 1;i < n; i++)
        {
            left[i] = 1;
            for(j =0; j<i ;j++)
            {
                if(a[i] > a[j] && left[i] < left[j] + 1)
                    left[i] = left[j] + 1;
            }
        }

        //右侧最长上升子序列
        right[n-1] = 1;
        for(i = n-2; i >= 0; i--)
        {
            right[i] = 1;
            for(j = n-1;j > i;j--)
            {
                if(a[i] > a[j] && right[i] < right[j] + 1)
                {
                    right[i] = right[j] + 1;
                }
            }
        }

        for(i = 0; i < n; i++)
        {
            if(left[i] + right[i] - 1 > cnt)
                cnt = left[i] + right[i] - 1;
        }

        printf("%d\n",n - cnt);
    }

    return 0;
}

抱歉!评论已关闭.