问题描述
虽然const_bh的游戏造诣仅高于青铜六选手zbt,但是他的算法造诣也仅高于日常打铁的吃瓜
群众zbt。但一日,const_bh偶有奇遇,遇到一位ACMdalao名曰Mengjiji,const_bh非常珍惜
这次机会,于是和Mengjiji一起搞了一场比(p)赛(y)。
比赛共有n道题,每道题有一个难度值,比赛要求题目必须按顺序逐个去做,为了减轻的蒟蒻
const_bh的压力,Mengjiji把原来的题目序列分成了两个序列,他和const_bh每人各负责
一个序列的题目,已知每个人将要面对的挑战值为他所负责的序列的相邻两个数的差的绝对值
一考const_bh,const_bh当然不会了,于是他偷偷的将这个问题用手机发给了聪明的你。
输入描述
输入包括两行,第一行有一个n(n<=2000),代表题目的总数。
第二行有n个数,第i个数a[i]代表第i道题的难度值为a[i]( 0< = a[i] < = 1000000000 ).
输出描述
输出仅一行,一个数字代表两个人挑战值和的最小值。
样例输入
5
1 2 1 3 4
样例输出
2
来源
第三届山西省大学生程序设计大赛
提示
将 【1,2,1,3,4】分成【1,1】和【2,3,4】两个序列,第一个序列的挑战值为0,第二个序列的挑战值为2.所以和为2.
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
//4 20 8 5 1 9
int n;
long long f[2005][2005],a[2005],dp[2005][2005],mn=1e18;
int main()
{
freopen("1.in","r",stdin);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
if(n<=2){
cout<<0<<endl;return 0;
}
for(int i=1;i<=n;i++)
for(int j=0;j<i;j++)
{
if(j==0)
f[j][i]=0;
else
f[j][i]=abs(a[i]-a[j]);
}
// for(int i=1;i<=n;i++)for(int j=0;j<i;j++)cout<<f[j][i]<<endl;
memset(dp,0x3f3f3f3f,sizeof dp);
dp[0][0]=0;
for(int i=1;i<=n;i++)
{
dp[0][i]=dp[0][i-1]+f[i-1][i];//write to f[i][i-1] that is error
}
// for(int i=1;i<=n;i++)
// {
// cout<<0<<","<<i<<","<<dp[0][i]<<" "<<endl;
// }
for(int i=2;i<=n;i++)//o(n^2)
for(int j=1;j<i;j++)
{
if(j==i-1)
{
for(int x=0;x<j;x++)
dp[j][i]=min(dp[j][i],dp[x][j]+f[x][i]);
}
else
{
dp[j][i]=dp[j][i-1]+f[i-1][i];
}
// cout<<j<<","<<i<<","<<dp[j][i]<<endl;
}
for(int i=1;i<=n;i++)
{
if(dp[i][n]<mn) mn=dp[i][n];
}
cout<<mn<<endl;
return 0;
}
/*
5
7 2 4 1 9
f[0][1]=0
f[0][2]=0
f[1][2]=5
f[0][3]=0
f[1][3]=3
f[2][3]=2
dp[1][2]=0
dp[1][3]=2 (7) (2,4)
dp[2][3]=3 (2) (7,4)
dp[1][4]=5 (7) (2,4,1)
dp[2][4]=6 (2) (7,4,1)
*/