[编程题] 合唱

时间限制:2秒

空间限制:131072K

小Q和牛博士合唱一首歌曲,这首歌曲由n个音调组成,每个音调由一个正整数表示。
对于每个音调要么由小Q演唱要么由牛博士演唱,对于一系列音调演唱的难度等于所有相邻音调变化幅度之和, 例如一个音调序列是8, 8, 13, 12, 那么它的难度等于|8 - 8| + |13 - 8| + |12 - 13| = 6(其中||表示绝对值)。
现在要对把这n个音调分配给小Q或牛博士,让他们演唱的难度之和最小,请你算算最小的难度和是多少。
如样例所示: 小Q选择演唱{5, 6}难度为1, 牛博士选择演唱{1, 2, 1}难度为2,难度之和为3,这一个是最小难度和的方案了。

输入描述:
输入包括两行,第一行一个正整数n(1 ≤ n ≤ 2000) 第二行n个整数v[i](1 ≤ v[i] ≤ 10^6), 表示每个音调。
输出描述:
输出一个整数,表示小Q和牛博士演唱最小的难度和是多少。
输入例子1:
5
1 5 6 2 1
输出例子1:
3

1 算法原理:

题目其实就是把一个数组分成两组,求每一组的相邻元素差的绝对值之和,再求它们的和,求最小值。

假设数组被分为A组B组,定义:

dp[i][j] (0<=i, j <= n - 1):

如下图左方所示,第i个元素分在了A组,第j个元素分在了B组,小于等于max(i, j)的元素都已经分完,大于max(i, j)的元素还没有分。其中*表示所有小于max(i, j)的元素。

如下图右方所示,所有的元素都已经分完。其中?表示所有大于max(i, j)的元素。

dp[i][j]记录把大于max(i, j)的元素(即图中的?)分完从而增加的和的最小值。也就是说,dp[i][j]仅记录添加了[max(i, j)+1, n]的元素引起的和的增加,且仅记录最小值。

A: *****i                       A: *****i????

==>

B: ***j                          B: ***j????????

PS:有点拗口,我也是分析了大牛的源码之后总结出来的。

易得,dp[i][j] = dp[j][i]

计算结果(求最小值):

当n <= 2时,最小值为0

当n > 2时,分组后为最小值的情况下,A,B组一定都有元素,且其中位置在[0, i]  (0 <= i < n-1) 的元素都分在了一组,第i+1个元素分在了另一组。因此,最小值为min{dp][i][i+1] + abs_sum(arr[0,...,i]), 0 <= i < n-1}

2 递推公式:

(1) max(i, j) == n - 1时, 所有元素分配完毕,因此 dp[i][j] = 0

(2) max(i, j) < n - 1时,下一个元素next = max(i, j) + 1有两种分配分法:

(2.1)  next分在A组:

A: *****i                       A: *****i next

==>

B: ***j                          B: ***j

则 dp[i][j] = dp[next][j] + abs(arr[next] - arr[i])

(2.2)  next分在B组:

A: *****i                       A: *****i

==>

B: ***j                          B: ***j next

则dp[i][j] = dp[i][next] + abs(arr[next] - arr[j])

因此 :

dp[i][j] = min(dp[next][j] + abs(arr[next] - arr[i]) , dp[i][next] + abs(arr[next] - arr[j]))

3 源码:

#include <stdlib.h>
#include <stdio.h>inline int max(int x, int y)
{return x > y ? x : y;
}inline int min(int x, int y)
{return x < y ? x : y;
}inline int abs_diff(int x, int y)
{return x > y ? x - y : y - x;
}int get_min_sum(int **dp, int *arr, int n)
{int i, j;int next;int res;int first_i_sum;for (i = 0; i < n; i++) dp[i][n - 1] = 0;for (j = 0; j < n; j++) dp[n - 1][j] = 0;for (i = n - 2; i >= 0; i--){for (j = n - 2; j >= 0; j--){next = max(i, j) + 1;dp[i][j] = min(dp[next][j] + abs_diff(arr[next], arr[i]) , dp[i][next] + abs_diff(arr[next], arr[j]));}}res = dp[0][1];first_i_sum = 0;for (i = 1; i < n - 1; i++){first_i_sum += abs_diff(arr[i - 1], arr[i]);res = min(res, dp[i][i + 1] + first_i_sum);}return res;
}int main()
{int n;int *arr;int **dp;int res;int i;scanf("%d", &n);if (n <= 2){printf("0");return 0;}arr = (int *)malloc(sizeof(*arr) * n);for (i = 0; i < n; i++) {scanf("%d", &arr[i]);}dp = (int **)malloc(sizeof(*dp) * n);for (i = 0; i < n; i++){dp[i] = (int *)malloc(sizeof(*dp[0]) * n);}res = get_min_sum(dp, arr, n);printf("%d", res);for (i = 0; i < n; i++){free(dp[i]);}free(dp);free(arr);return 0;
}

网易2018校园招聘编程题真题 合唱相关推荐

  1. 网易2018校园招聘编程题真题集合

    1/8 [编程题]魔法币 #include<bits/stdc++.h> using namespace std; #define clr(a) memset(a, 0, sizeof(a ...

  2. 网易2018校园招聘编程题真题集合 详解

    ##编程题 ###一.魔法币 ####描述: 小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入 xxx(xxx 可以为 00 ...

  3. [2018]试卷: 网易2018校园招聘编程题真题集合

    [编程题] 魔法币 小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0)个魔法币产生更多的魔法币. 魔法机器1: ...

  4. [网易]2018校园招聘编程题真题集合

    题目:  小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0)个魔法币产生更多的魔法币.  魔法机器1:如果投入 ...

  5. 网易2018校园招聘编程题真题集合2相反数

    这道题是说给出一个数,求他的"相反数",相反数是先把原先的数倒过来,然后把他和倒过来之前的相加. #include <iostream> #include <st ...

  6. 网易2018校园招聘编程题真题集合1魔法币

    一开始没有理解题意:这道题是说,每次把手头上的魔法币全都投入. 这道题一开始用了回溯,只通过80%,大数据通不过. #include <iostream> #include <str ...

  7. 网易2018校园招聘编程题真题集合3字符串碎片

    这道题不难,需要存下碎片的个数,就遍历字符串,保存刚刚遍历过的字符,如果这个字符和刚刚的字符不同,说明到了一个新的碎片,碎片个数+1. 最后存储保留两位的double,用一个char数组来存,spri ...

  8. 网易2018校园招聘编程题真题-[编程题] 魔法币

    问题描述: 时间限制:1秒 空间限制:32768K 小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0)个魔法币 ...

  9. 网易2018校园招聘编程题

    [编程题] 魔法币 时间限制:1秒 空间限制:32768K 小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0) ...

  10. 数据分析真题日刷 | 网易2018校园招聘数据分析工程师笔试卷

    七月第一天,希望大家下半年都能「翻身」! 今日真题 网易2018校园招聘数据分析工程师笔试卷(来源:牛客网) 题型 客观题:单选20道:主观题:问答3道 完成时间 120分钟 牛客网评估难度系数 四颗 ...

最新文章

  1. Spring框架简介
  2. CSS3常用动画总结
  3. 华为鸿蒙会议安排,2020华为HDC日程确定,鸿蒙、HMS以及EMUI 11成最关注点
  4. 系统如何启动数据库服务器,怎么启动sql数据库服务器
  5. 简约易收录的导航网站源码
  6. 今日恐慌与贪婪指数为61 贪婪程度有所缓解
  7. python与mongodb更新_Python对MongoDB增删改查
  8. STM32机器人控制开发教程No.2 霍尔编码器电机测速以及增量式PID控制(基于HAL库)
  9. Windows安全中心打开空白
  10. kero入门学习总结
  11. matlab怎么做空间计量,六步学会用MATLAB做空间计量回归详细步骤
  12. 输入日期,查看当天是星期几
  13. Linux—常用十大命令
  14. VSCode配置JavaScript基于Node.js环境
  15. 《算法笔记》9.4小节 9.5小节——数据结构专题(2)->二叉查找树(BST)->平衡二叉树(AVL)
  16. Java/Flex/.Net 三国演绎 之 关公战秦琼
  17. 1万小时贫穷定律:为什么你越忙越穷
  18. 员工绩效考核管理PPT模板-优页文档
  19. linux内核协议栈 之 GSO逻辑分析
  20. 【高速数字化仪应用案例系列】虹科Spectrum在天文领域的应用

热门文章

  1. 我对Backbone的认识
  2. SQLite介绍及使用
  3. 转载 JavaScript的24条实用建议
  4. 极光短信验证码JAVA_Android如何集成极光短信验证
  5. Spring Boot入门(7)-单元测试
  6. ajax一直返回 error
  7. WARN No appenders could be found for logger的解决方法
  8. wordpress自定义404页面
  9. rust投递箱连接箱子_海门市围板箱定制围板箱内衬
  10. bigdecimal计算开n次方_随笔:HashMap中容量为什么是2的次方数?