HWOJ-合唱队

计算最少出列多少位同学,使得剩下的同学排成合唱队形

说明:

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。 
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,   则他们的身高满足存在i(1<=i<=K)使得Ti<T2<......<Ti-1<Ti>Ti+1>......>TK。 
     你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入
整数N

一行整数,空格隔开,N位同学身高

输出
最少需要几位同学出列

样例输入 8 186 186 150 200 160 130 197 200
样例输出 4

这个问题实际就是在求一个最长递增子序列,和最长递减子序列的问题,对应求和找到最大的那个temp=arrayLenUp[i]+arrayLenDown[N-1-i];,即是合唱队的长度-1。

Java代码:通过

import java.util.Scanner;

public class Main {

    public static void main(String[] args){

        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入一个整数:");
        int N=scanner.nextInt();
        int[] height=new int[N];
        for (int i = 0; i < N; i++) {
            height[i]=scanner.nextInt();
        }
        Main main=new Main();
        int[] arrayLenUp=main.getLISUp(height);
        for(int i:arrayLenUp)
            System.out.print(i+",");
        System.out.println();
        int[] arrayLenDown=main.getLISDown(height);
        for(int i:arrayLenDown)
            System.out.print(i+",");
        System.out.println();
        int total=2;
        int temp;
        for (int i = 0; i < N; i++) { //对应求和找到最大的那个
            temp=arrayLenUp[i]+arrayLenDown[N-1-i];
            if (temp>total) {
                total=temp;
            }
        }
        System.out.println((N-total+1)); //输出最终结果
        scanner.close();

    }

    public int binarySearchPosition(int arrayOut[],int left,int right,int key){ //二分查找要替换的位置

        int mid;

        if (arrayOut[right]<key) {
            return right+1;
        }else {
            while(left<right){
                mid=(left+right)>>1;
                if (arrayOut[mid]<key) {
                    left=mid+1;
                }else {
                    right=mid;
                }
            }
                return left;
        }

    }

    public int[] getLISUp(int[] arrayIn){ //获取最长递增子序列并把它们保存在数组arrayLen中

        int len=1;
        int position;
        int[] arrayOut=new int[arrayIn.length+1];
        arrayOut[1]=arrayIn[0];
        int[] arrayLen=new int[arrayIn.length];
        arrayLen[0]=1;
        for (int i = 1; i < arrayIn.length; i++) {
            position=binarySearchPosition(arrayOut, 1, len, arrayIn[i]);
            arrayOut[position]=arrayIn[i];
            if (position>len) {
                len=position;
            }
            arrayLen[i]=position;
        }
        return arrayLen;
    }

    public int[] getLISDown(int[] arrayIn){ ////获取最长递减子序列并把它们保存在数组arrayLen中
        int[] arrayReverse=new int[arrayIn.length];
        int[] arrayLen=new int[arrayIn.length];
        for (int i = 0; i < arrayReverse.length; i++) { //将最长递减子序列问题转换为最长递增子序列问题
            arrayReverse[i]=arrayIn[arrayIn.length-1-i];
        }
        arrayLen=getLISUp(arrayReverse);
        return arrayLen;
    }

}

C代码:没有通过

#include "iostream"  

#include "stdio.h"  

#include "math.h"  

#include "vector"  

#include "queue"  

#include "memory.h"  

#include "algorithm"  

#include "string"  

using namespace std;  

int inc1[200],inc2[200],a[200];  

//inc1-->longest increase array from head to tail  

//inc2-->longest increase array from tail to head  

int main()  

{  

    int n;  

    while(scanf("%d",&n)!=EOF)  

    {  

        int ans=0,i,j;  

        for(i=1;i<=n;i++)  

            scanf("%d",&a[i]);  

        inc1[1]=1;  

        for(i=2;i<=n;i++)  

        {  

            inc1[i]=1;  

            for(j=1;j<i;j++)  

                if(a[i]>a[j]&&inc1[j]+1>inc1[i])  

                    inc1[i]=inc1[j]+1;  

        }  

        inc2[n]=1;  

        for(i=n-1;i>=1;i--)  

        {  

            inc2[i]=1;  

            for(j=n;j>i;j--)  

                if(a[j]<a[i]&&inc2[j]+1>inc2[i])  

                    inc2[i]=inc2[j]+1;  

        }  

        for(i=1;i<=n;i++)  

            if(inc1[i]+inc2[i]-1>ans)   

                ans=inc1[i]+inc2[i]-1;  

        printf("%d\n",n-ans);  

    }  

    return 0;  

}  
时间: 2024-08-26 14:52:21

HWOJ-合唱队的相关文章

1996: [Hnoi2010]chorus 合唱队

1996: [Hnoi2010]chorus 合唱队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1057  Solved: 681[Submit][Status][Discuss] Description Input Output Sample Input 4 1701 1702 1703 1704 Sample Output 8 HINT Source 题解:萌萌哒DP题,其实和我一开始想的暴力方法很接近,基本上就是记忆化暴力,然后转变为循环形

bzoj1196:[Hnoi2010]chorus 合唱队

这数据范围明显的区间dp啊...然而据说二维会wa...那就写三维把... #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(

【BZOJ1996】【HNOI2010】合唱队 [区间DP]

合唱队 Time Limit: 4 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Description Input Output Sample Input 4 1701 1702 1703 1704 Sample Output 8 HINT Main idea 给定一个元素两两不相等的目标序列,每次按照给定方式将一个元素加入到序列当中,问得到目标序列的方案有几种.(加元素的方式:如果加的这个元素比上一个加入的元素小的话则放在队头,否则放在队

华为0基础——合唱队

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveG1oMTk1NA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" > 提示:这是属于动态规划问题.动态规划算法通经常使用于求解具有某种最优性质的问题.在这类问题中.可能会有很多可行解.每个解都相应于一个值.我们希望找到具有最优值的解. 事实上这道题目有一些问题:不能交换位置,这个关键的信息在

BZOJ 1996: [Hnoi2010]chorus 合唱队(dp)

简单的dp题..不能更水了.. --------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define rep(i,n) for(int i=0;i<n;++i) #define clr(x,c) memset(x,c,sizeof(x

华为初级——合唱队

提示:这是属于动态规划问题.动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解. 其实这道题目有一些问题:不能交换位置,这个关键的信息在题目中间没有进行说明. 编程思路是:需要三个数组,第一个数组存放原数据.第二个数组用于存放人数:从左向右遍历时,对于当前的数据(身高),寻找符合条件的人数,要求是从小到大排列的最大数.第三个数组用于存放人数:从右向左遍历,对于当前的数据,寻找符合条件的人数,要求从大到小排列的最大数

[华为机试练习题]37.合唱队

题目 描述: 计算最少出列多少位同学,使得剩下的同学排成合唱队形 说明: N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2-,K,他们的身高分别为T1,T2,-,TK, 则他们的身高满足存在i(1<=i<=K)使得T1 < T2 <...... < Ti-1 < Ti >Ti+1 >......>TK. 你的任务是,已知所有N位同学的身高,计算最少

华为OJ 合唱队

描述:N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, -, K,他们的身高分别为T1, T2, -, TK,则他们的身高满足T1 < T2 < - < Ti , Ti > Ti+1 > - > TK (1 <= i <= K) . 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形. 输入:第

bzoj 1996: [Hnoi2010]chorus 合唱队

Description Input Output Sample Input 4 1701 1702 1703 1704 Sample Output 8 HINT Source 因为只会在区间的两端进行操作,这很容易让我们想到一种区间dp的模型... dp[i][j]表示区间[i,j]已经匹配上了的方案数,因为我们需要知道上一个填的数是什么所以多加一维, dp[i][j][0]表示最后填的数在区间左边,dp[i][j][1]表示最后填的数在区间右边, 这样我们可以确切的知道上一个填的数和当前要填的

合唱队

描述 计算最少出列多少位同学,使得剩下的同学排成合唱队形 说明: N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,   则他们的身高满足存在i(1<=i<=K)使得Ti<T2<......<Ti-1<Ti>Ti+1>......>TK.      你的任务是,已知所有N位同学的身高,计算最少需要几位同学