Description
炸弹是塔利班对付美军的武器之一。默罕默德在塔利班的主要任务是做炸弹。默罕默德所做的新型炸弹由若干个小炸弹组成,每个小炸弹有一个威力值,整个炸弹的威力值是组成这个炸弹的最大威力差的平方,即(max-min)^2,假设一个炸弹有5个小炸弹组成,威力分别为5 9 8 2 1,那么它的威力为(9-1)^2=64。
时间紧任务多默罕默德的师傅兼老爸老默罕默德又不在,默罕默德不敢调整小炸弹的顺序,只能确定它们的分组。请你帮助默罕默德确定小炸药的分组,使制造出的炸弹拥有最大的威力和。
Input
第一行有 1 个正整数N( 1 <= N <= 1000),表示有N个小炸弹。
第二行有N个数,其中第i个数Ai表示第i个小炸弹的威力值( 0 <= Ai <= 1000)。
Output
输出炸弹的威力和。
Sample Input
6
5 9 8 2 1 6
Sample Output
77
Source
思路:
把n个炸弹分为任意组,前提是炸弹顺序不能变,例如炸弹为1,2,3,4
那么可以分为{1},{2,3},{4}
或者{1,2},{3},{4}
说白话就是分为若干个连续的子序列
首先v2动态规划八字金句(看分析图,图中的某些部分看不懂我下面会一一解释)
第一
假设有这样一个大小为n的炸弹数组
index | 0 | 1 | 2 | ..... | i | .... | n-1 |
val | 5 | 4 | 6 | ..... | 1 | .... | 3 |
当我们选择到第i个下标的炸弹时(后面的统统不考虑):
我们可以考虑有哪些情况?
第i个炸弹可以与前面若干个炸弹组合成一个连续的炸弹组
例如{i-2,i-1,i}这三个炸弹组成一个炸弹组
那么就有i+1种情况:
{i-1,i}
{i-2,i-1,i}
{i-3,i-2,i-1,i}
....
{0,1,2,....,i-2,i-1,i}
第二
看懂了上面的解释
我们就可以定义一下通项了,设dp[i]为【0-i】范围内组成炸弹威力最大的值
起调也出来了,我们要求的最终结果就是dp[n-1],表示【0-n-1】范围内组成炸弹威力的最大值
第三
继续第一步的分析,我们选择到第i个炸弹
有i+1种可能的情况,我们是否可以枚举每一种情况,然后取最大值,这个值是不是就是dp[i]的值,即【0-i】范围内组成炸弹威力的最大值
那么我们用一个变量j来辅助枚举
转移方程伪代码:
for( j 范围 [0,i] )
{
dp[i]=max(dp[i], dp[j-1]+pre[j][i]);
}
dp[j-1]表示0-j-1范围内组成炸弹的最大值,pre[j][i]表示j-i范围内组成炸弹的威力值
pre[i][j]数组需要我们提前预处理,表示的就是从下标i到下表j区间内炸弹的威力值
第四
到此为止
通项:dp[i]
出口:dp[0]=0
起调:dp[n-1]
转移:
dp[i]=max(dp[i],dp[j-1]+pre[j][i])
代码:
#include<iostream>
#include<vector>
using namespace std;
int a[1005];
int main()
{
//输入
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
vector<vector<int> > pre(n, vector<int>(n, 0));
//pre预处理数组 下标表示从i到j区间内炸弹威力值
//例如i=1,j=1表示下标为1的炸弹单独成组的炸弹威力值为0
for (int i = 0; i < n; i++)
{
int max_v = a[i];
int min_v = a[i];
for (int j = i; j < n; j++)
{
if (a[j] > max_v)max_v = a[j];
if (a[j] < min_v)min_v = a[j];
pre[i][j] = (max_v - min_v) * (max_v - min_v);
}
}
//pre表格输出
/*
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d ", pre[i][j]);
}
printf("\n");
}
*/
vector<int> dp(n + 1, 0);
dp[0] = 0;
for (int i = 1; i < n; i++)
{
for (int j = 0; j <= i; j++)
{
//注意j的取值,当j=0时,j-1=-1会数组越界,手动判断一下
if (j == 0)
dp[i] = max(dp[i], 0 + pre[j][i]);
else
dp[i]= max(dp[i], dp[j-1] + pre[j][i]);
}
}
printf("%d\n", dp[n - 1]);
return 0;
}
如果还不清楚的话可以私信我