和Mengjiji一起攻克难关

和Mengjiji一起攻克难关

时间限制: C/C++ 1000ms; Java 2000ms 内存限制: 65535KB
通过次数: 11 总提交次数: 35
问题描述

       虽然const_bh的游戏造诣仅高于青铜六选手zbt,但是他的算法造诣也仅高于日常打铁的吃瓜群众zbt。但一日,const_bh偶有奇遇,遇到一位ACMdalao名曰Mengjiji,const_bh非常珍惜这次机会,于是和Mengjiji一起搞了一场比(p)赛(y)。

       比赛共有n道题,每道题有一个难度值,比赛要求题目必须按顺序逐个去做,为了减轻的蒟蒻const_bh的压力,Mengjiji把原来的题目序列分成了两个序列,他和const_bh每人各负责一个序列的题目,已知每个人将要面对的挑战值为他所负责的序列的相邻两个数的差的绝对值的总和。Mengjiji身为dalao当然知道怎么分工使两个人的挑战值的和最小了,但是他想考一考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.

思路:

规定dp[i][j](i>j)为A队列中最后一个元素的下标为i,B队列中最后一个元素的下标为j,时各相邻元素绝对值的最小和;

若只有两个元素,则结果为0;

n>2时可能有这么两种情况:

dp[i][i-1]:(相邻的两个元素分别放入两个队列中,在放入下标为i的元素时放到了与i-1不同的队列中),先初始化dp[i][i-1]=dp[i-1][0],再有dp方程dp[i][i-1]=min(dp[i][i-1],dp[i-1][j]+abs(a[i]-a[j]));j:0->i-2

dp[i][j]:(相邻的两个元素放入了同一个队列中,在放入下标为i的元素时放到了与i-1相同的队列中),有dp方程dp[i][j]=dp[i-1][j]+abs(a[i]-a[i-1]);j:0->i-2


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define me(x,y) memset(x,y,sizeof(x))
#define sd(x) scanf("%d",&x)
#define ss(x) scanf("%s",x)
#define sf(x) scanf("%f",&x)
#define slf(x) scanf("%lf",&x)
#define slld(x) scanf("%lld",&x)
#define pd(x) printf("%d\n",x)
#define plld(x) printf("%lld\n",x)
#define ps(x) printf("%s\n",x)
#define max(x,y) (x>=y?x:y)
#define min(x,y) (x<y?x:y)
#define sum(x,y) (x+y)
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=2005;

ll a[maxn];
ll dp[maxn][maxn];
int n;

int main() {
    sd(n);
    for(int i=1;i<=n;i++) slld(a[i]);
    if(n<=2) pd(0);
    else {

        dp[2][0]=abs(a[2]-a[1]);

        for(int i=3;i<=n;i++) {
            dp[i][i-1]=dp[i-1][0];
            for(int j=0;j<=i-2;j++) {
                dp[i][i-1]=min(dp[i][i-1],dp[i-1][j]+abs(a[i]-a[j]));
                dp[i][j]=dp[i-1][j]+abs(a[i]-a[i-1]);
            }
        }
        ll ans=maxv;

        for(int i=0;i<n;i++)
            ans=min(ans,dp[n][i]);
        plld(ans);
    }

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水能zai舟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值