1 题目
(此题来源牛客网网易2018秋招笔试真题)
1.1 题目描述
小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,这一个是最小难度和的方案了。
1.2 输入描述
输入包括两行,第一行只有一个正整数n(1 <= n <= 2000),第二行n个正整数v[i](1 <= v[i] <= 10^6),表示每个音调。
1.3 输出描述
输出一个整数,表示难度之和最小为多少。
1.4 输入示例
5
1 5 6 2 1
1.5 输出示例
3 //1 2 1一个人唱,5 6另一个人唱
2 问题分析
把问题直接翻译过来,就是给一个数组,将其分成两个数组(不能改变原有次序),使得这两个数组的各自元素之差的绝对值的和最小。
采用动态规划解题:
用一个二维数组,d[i,j]表示前i个音符中,有个人最后一次唱的时第j个音符,从j+1到i全是由另一个人唱的,对应的难度之和。外层循环用i表示,从第1个音符一直到最后一个音符,内层循环用j表示,表示其中有个人最后唱的一个音符时j。
当循环开始时候,即是否更新d[i,j]时候,考虑两种情况:1)唱最后一个音符时候换人,2)不换人。
3 代码编写
//还没有做完
#include <iostream>
#include <algorithm>
using namespace std;
void test(){
int n; //一共有n个音符
cin>>n;
int* v = new int[n+1]; //音符数组
for(int i = 1;i <= n;i++)
cin>>v[i];
v[0] = v[1]; //把第0个也初始化了
int** d = new int*[n+1]; //初始化二维数组
for(int i = 0;i <= n;i++)
d[i] = new int[n+1];
for(int i = 0;i <= n;i++)
for(int j = 0;j <= n;j++)
d[i][j] = 0;
for(int i = 1;i <= n;i++){
arr[i] = arr[i-1] + abs(v[i] - v[i-1]);
for(int j = 0;j < i;j++){
d[i][j] = d[i-1,j] + abs(v[i] - v[i-1]);
}
int t1;
for(int k = 0;k <= i-1;k++){
int t2 = d[i-1][k] +
}
int main()
{
test();
return 0;
}