`
200830740306
  • 浏览: 109404 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

合唱队形

阅读更多
#include <stdio.h>
#include <memory.h>
#include <algorithm>
using namespace std;
#define MAX 32767
#define MIN -32767
int b[105][105] = {0}; //用于构造最长公共子序列
int c[105][105] = {0}; //记录最长公共子序列长度
int normal[105] = {0}; //记录身高序列
int n; //记录身高序列的长度
int increase[105] = {0}; //记录递增序列
int decrease[105] = {0}; //记录递减序列
int temp1[105] = {0}; //记录最长递增子序列
int count1 = 0; //记录最长递增子序列的长度
int temp2[105] = {0}; //记录最长递减子序列
int count2 = 0; //记录最长递减子序列的长度
int m1 = 0, m2 = 0; //分别记录递增和递减序列的长度

//排序函数的一个参数,逆序用的

int cmp(int aa, int bb) {
    return aa>bb;
}
//求最长公共子序列

void LCSLength(int x[], int y[], int m, int n) {
//    for (int i = 0; i <= m; i++) {
//        c[i][0] = 0;
//    }
//    for (int i = 0; i <= n; i++) {
//        c[0][i] = 0;
//    }
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (x[i - 1] == y[j - 1]) {
                c[i][j] = c[i - 1][j - 1] + 1;
                b[i][j] = 0;
            } else if (c[i - 1][j] >= c[i][j - 1]) {
                c[i][j] = c[i - 1][j];
                b[i][j] = 1;
            } else {
                c[i][j] = c[i][j - 1];
                b[i][j] = -1;
            }
        }
    }
}
//构造最长公共子序列,递增

void printLCS1(int x[], int m, int n, int temp[]) {
    int i = m;
    int j = n;
    if (i == 0 || j == 0) {
        return;
    }
    if (b[i][j] == 0) {
        printLCS1(x, i - 1, j - 1, temp);
        temp[count1++] = x[i - 1];
        // printf("%d ", x[i - 1]);
    } else if (b[i][j] == 1) {
        printLCS1(x, i - 1, j, temp);
    } else {
        printLCS1(x, i, j - 1, temp);
    }
}
//构造最长公共子序列,递减

void printLCS2(int x[], int m, int n, int temp[]) {
    int i = m;
    int j = n;
    if (i == 0 || j == 0) {
        return;
    }
    if (b[i][j] == 0) {
        printLCS2(x, i - 1, j - 1, temp);
        temp[count2++] = x[i - 1];
        // printf("%d ", x[i - 1]);
    } else if (b[i][j] == 1) {
        printLCS2(x, i - 1, j, temp);
    } else {
        printLCS2(x, i, j - 1, temp);
    }
}

/*
 * N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的 K位同学排成合唱队形。
 * 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,
 * 则他们的身高满足T1 < T2 < ...< Ti > Ti+1 > … > TK (1 <= i <= K)。
 * 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
 * Input
 * 输入包含若干个测试用例。
 * 对于每个测试用例,输入第一行是一个整数N(2<=N<=100),表示同学的总数。
 * 第二行有N个整数,用空格分隔,第i个整数 Ti(130<=Ti<=230)是第i位同学的身高(厘米)。
 * 当输入同学总数N为0时表示输入结束。
 * Output
 * 对于每个测试案例,输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
 * Sample Input
 * 8
 * 186 186 150 200 160 130 197 220
 * 3
 * 150 130 140
 * 0
 * Sample Output
 * 4
 * 1
 * Hint
 * 合唱队形满足T1 < T2 < ...< Ti > Ti+1 > … > TK (1 <= i <= K),其中里面最具有指标性意义的人是Ti,
 * 由于(1 <= i <= K),意味着每个人都可能是作为中间的指标性人物,因此可枚举所有情况.
 * 对于每种情况,指标性人物往左应求一个最长的队列,往右也应求一最长的队列(当然此队列要包含指标人物本身).
 * 如下例:
 * 8个人
 *                               186 186 150  200 160 130 197 220
 * 以第i个人作为中心往左的最长序列:1    1   1   2   2    1   3  4
 * 以第i个人作为中心往右的最长序列:3    3   2   3   2    1   1  1
 *
 * 思路:
 * 求身高序列的最长递增(注意不是非递减)子序列和最长递减(注意不是递增)子序列
 * 然后两个序列合并即可以求出最长的合唱队形,然后就可以求出去除的人数了
 * 而最长递增和最长递减子序列时,可以先排序,再去除重复的,转为求最长公共子序列
 */
int main() {
    int i, j, result;
    while (scanf("%d", &n)) {
        m1 = n;
        m2 = n;
        if (n == 0) {
            break;
        }
        for (i = 0; i < n; i++) {
            scanf("%d", &normal[i]);
            decrease[i] = normal[i];
            increase[i] = normal[i];
        }
        //排序
        sort(increase, increase + n);
        sort(decrease, decrease + n, cmp);
        //去掉重复的数字,把重复的数字置最大值,排序后取前面的数
        for (i = 0, j = 1; i < n;) {
            if (increase[i] == increase[j]) {
                increase[i] = MAX;
                i = j;
                j++;
                m1--;
            } else {
                i++;
                j++;
            }
        }
        sort(increase, increase + n);
        //去掉重复的数字,把重复的数字置最小值,排序后取前面的数
        for (i = 0, j = 1; i < n;) {
            if (decrease[i] == decrease[j]) {
                decrease[i] = MIN;
                i = j;
                j++;
                m2--;
            } else {
                i++;
                j++;
            }
        }
        sort(decrease, decrease + n, cmp);
        //求最长递增子序列
        LCSLength(normal, increase, n, m1);
        count1 = 0;
        printLCS1(normal, n, m1, temp1);
        //        for (i = 0; i < count1; i++) {
        //            printf("%d ", temp1[i]);
        //        }
        //        printf("\n");
        memset(c, 0, sizeof (c));
        memset(b, 0, sizeof (b));
        //求最长递减子序列
        LCSLength(normal, decrease, n, m2);
        count2 = 0;
        printLCS2(normal, n, m2, temp2);
        //        for (i = 0; i < count2; i++) {
        //            printf("%d ", temp2[i]);
        //        }
        //        printf("\n");

        //合并两个最长递增和递减子序列,排成合唱队形
        for (i = count1 - 1, j = 0; i >= 0 && j < count2;) {
            if (temp1[i] > temp2[j]) {
                i--;
            } else if (temp1[i] < temp2[j]) {
                j++;
            } else {
                break;
            }
        }
        if (count1 == 0 || count2 == 0) {
            result = 0;
        } else if (i < 0 || j >= count2) {
            result = count1 > count2 ? count1 : count2;
            result = n - result;
        } else {
            result = n - (i + count2 - j);
            int tem = count1 > count2 ? count1 : count2;
            tem = n - tem;
            result = tem < result ? tem : result;
        }
        //输出去掉最少的人数
        printf("%d\n", result);
        memset(c, 0, sizeof (c));
        memset(b, 0, sizeof (b));
        memset(temp1, 0, sizeof (temp1));
        memset(temp2, 0, sizeof (temp2));
    }
    return 1;
}

分享到:
评论

相关推荐

    合唱队形(剩下的同学排成合唱队形)

    根据给定的信息,本文将详细解释“合唱队形”这一概念以及如何通过编程解决与之相关的实际问题。本文首先会介绍合唱队形的基本定义及其在实际中的应用背景,随后将详细解析给定代码的主要功能及其实现逻辑。 ### ...

    合唱队形实现算法acm

    N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高...

    合唱队形 解题报告 NOIP

    此题是NOIP(全国青少年信息学奥林匹克联赛)中的一道经典算法题,题目名为“合唱队形”(ChorusBy Len),主要考察的是动态规划和分割序列的优化策略。以下是对该题目的详细分析: 1. **问题理解**: - 给定一个...

    54、1264:【例9.8】合唱队形+书画相关链接(十八)-2020-01-19(A).pdf

    2. 合唱队形定义:合唱队形是指在一行同学中,找到一段子序列,使得这段子序列满足两边的同学身高较低,中间的同学身高递增然后递减。即对于任一中间位置的i(1 ),都存在T1 &lt; T2 &lt; ... &lt; Ti &gt; Ti+1 &gt; ... &gt; TK。 ...

    NOIP合唱队形源程序

    N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高...

    1264 合唱队形.cpp

    DP系列

    大型合唱排练情况简报.docx

    3. **歌曲选择与排练方法**:选择适合合唱的歌曲,如《唱歌祖国》,并结合传统的四声部合唱队形进行创新。利用梯形或倒梯形队形,以女高、女低、男高、男低四个基本声部为基础,灵活调整。排练时,要挑选声部小队长...

    初中音乐校本课程合唱基本训练知识教(学)案设计说明.doc

    本教(学)案旨在详细阐述歌唱的姿势以及合唱队形编排的两个重要方面,以期提升学生的合唱水平和整体音乐素养。 首先,歌唱姿势是合唱训练中的基础环节,它直接关系到演唱者发声的质量和身体的健康。在教学中,教师...

    《动态规划算法实验》实验报告.docx

    《动态规划算法实验》实验报告主要探讨了两个经典动态规划问题——0-1背包问题和合唱队形安排问题。这两个问题都是在优化决策过程中寻找最优解的经典实例。 **一、0-1背包问题** 0-1背包问题是一个经典的约束优化...

    动态规划dp

    2. **合唱队形问题**:要求找到最少需要出列的同学数量,使得剩下的同学能形成合唱队形(即身高从左到右先增后减)。同样可以采用动态规划。我们可以遍历所有同学,对于每个学生,检查其左侧是否存在严格升序的子...

    合唱排练软件 合唱排练系统 v1.06

    《合唱排练软件 合唱排练系统 v1.06》是一款专为合唱团设计的高效排练工具,旨在提升合唱团的练习效果和整体和谐性。该软件集成了多种功能,包括分声部教学、节拍器、伴奏控制等,能够满足不同层次合唱团队的需求。 ...

    合唱的组织与编排 课件.ppt

    - 不同声部的队形安排:如两声部、三声部和混声四部的合唱队形设计。 8. **合唱的基本训练**: - 发声训练:采用胸腹式联合呼吸法,深呼吸并将气息扩展至腰部,保持横膈膜的张力,以实现稳定而有力的发声。 这些...

    历届NOIp动态规划梳理解读PPT学习教案.pptx

    题目要求从一组学生中选出满足特定条件的子集,即这些子集内的学生按身高排列形成合唱队形,即部分子集内的学生身高是单调递增的,部分是单调递减的。解决此类问题,可以使用动态规划方法,通过比较每个学生的身高和...

    信息学奥赛试卷

    砝码称重问题、最小乘车费用问题、合唱队形问题和观光游览问题等,均需要参赛者对算法有深入的理解,并具备良好的问题解决能力。通过这些题目的训练,不仅可以提升参赛者的逻辑思维能力、分析能力和编程技巧,还能在...

    动态规划常见基础模型PPT学习教案.pptx

    合唱队形问题则需要同时从两端寻找最长的上升子序列,最终找到使K位同学满足合唱队形条件的最小人数。 滑雪问题实质上也是最长上升子序列的变种,通过调整高度数组,我们可以从高到低遍历,找到最长的“下坡”路径...

    代码 动态规划 特殊数据结构搜索、枚举

    1008 合唱队形 1017 最大0,1子矩阵 这题要想不超时,必须DP 1020 最大正方形 这题和1017很相似,不过有更快的解决方法 1021 背包问题 1022 Longest Common Sequence 也可用二叉搜索树(nlog时间)解决,见llj的书 ...

    2012 ACM试题

    要形成合唱队形,需要找到最小的K使得剩下的K个人按身高排列后满足条件。可以先对所有身高进行排序,然后从两边向中间扫描,统计满足条件的子序列。 T4 题目是一个经典的最优化问题,类似于区间覆盖。通过线段树或...

    《算法分析与设计》实验教学大纲.pdf

    3. 动态规划算法:实验内容包括0-1背包问题和合唱队形安排的编程解决。学生需掌握动态规划的基本策略,学习如何构建最优解决方案。 4. 回溯算法:实验涵盖了8皇后问题和批处理作业调度的回溯法求解。学生需理解回溯...

    二年级数学下册第八单元探索乐园8.1简单的排列组合课时练冀教版

    3. **小华、小芳和小红的合唱队形**: 类似于上一题的排列问题,但这里考察的是三个人的排列,而不是三个位置。因为每个人都可以站在队伍的开头、中间或结尾,所以总共有3!(3的阶乘)种排列方式,即3种不同的队形...

    少先队工作范文庆祝六一儿童节学校工作总结.doc

    学生们自编自演的节目精彩纷呈,尤其是六(1)班的合唱队形设计,展现了团队合作的力量。一年级的小朋友冯莹的精彩表演更是赢得了现场的热烈掌声,体现出了学校艺术教育的成果和孩子们对节日的热爱。 此外,活动...

Global site tag (gtag.js) - Google Analytics