视频讲解:GESP202609 六级 数组划分-信息学奥赛GESP等级考试真题解析
一、原题
题目描述
给定 n 个整数构成的数组 A=a1,a2,...,an。
你需要将数组 A 划分为若干非空连续子段。对于划分得到的某个子段,它的偏差值定义为子段内整数和的平方。划分方案的偏差值定义为所有子段偏差值之和。
你需要最小化划分方案的偏差值。
形式化地,你可以将 A 划分为若干非空连续子段 A1,A2,...,Ak,使得 A=A1+A2+...+Ak,这里的 + 代表数组的连接。对于 1≤i≤k,设数组 包含 mi 个整数。你需要最小化
。
输入格式
第一行,一个正整数 n,表示数组 A 的长度。
第二行,n 个整数 a1,a2,...,an,表示数组 A。
输出格式
一行,一个整数,表示划分方案偏差值的最小值。
输入输出样例
输入 #1
4
1 2 -3 4
输出 #1
6
输入 #2
6
-1 -1 4 -5 -1 4
输出 #2
0
说明/提示
对于 40% 的测试点,保证 0≤ai≤50。
对于所有测试点,保证 1≤n≤2000,−100≤ai≤100。
二、做题思路
1)填充数据
cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
//1)填充数据
//1.1)确定大小
int n;cin>>n;
//1.2)填充n个数据
int a[2005]={};
for(int i=1;i<=n;i++) cin>>a[i];
return 0;
}
2)dp状态转移

cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
//1)填充数据
//...
//2)dp状态转移
//2.1)循环每个数据
long long dp[2005]={};
for(int i=1;i<=n;i++){
//2.2)初始化为最大
dp[i]=LLONG_MAX;
//2.3)从当前为开始,计算累加和
long long sum=0;
for(int j=i;j>=1;j--){
sum+=a[j];
//2.4)之前的最优解+当前累计和平方
dp[i]=min(dp[j-1]+sum*sum,dp[i]);
}
}
//2.5)输出最优解
cout<<dp[n];
return 0;
}
三、答案
cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
//1)填充数据
//1.1)确定大小
int n;cin>>n;
//1.2)填充n个数据
int a[2005]={};
for(int i=1;i<=n;i++) cin>>a[i];
//2)dp状态转移
//2.1)循环每个数据
long long dp[2005]={};
for(int i=1;i<=n;i++){
//2.2)初始化为最大
dp[i]=LLONG_MAX;
//2.3)从当前为开始,计算累加和
long long sum=0;
for(int j=i;j>=1;j--){
sum+=a[j];
//2.4)之前的最优解+当前累计和平方
dp[i]=min(dp[j-1]+sum*sum,dp[i]);
}
}
//2.5)输出最优解
cout<<dp[n];
return 0;
}