FJUT Home_W的拆分序列(DP)题解
Problem Description
Home 现在给你一个序列要求你将这个序列拆成恰好两个子序列。且使得两个子序列的抖动系数之和最大。
对于一个序列c1,c2,c3,……cm. 其抖动系数=|c1-c2|+|c2-c3|+……+|cm-1-cm|
Input
单组数据,一个行是一个整数n.代表序列长度。
接下一行来有n个整数,a1,a2,a3,……an 代表这个序列
2<=n<=1000
1<=ai<=1e6
Output
输出一行代表在最优的拆分方案下,最大的抖动系数之和。注意其中任意一个子序列都不可以为空
思路:我们把dp[i][j]视为以i和j结尾的两列的最大值。
我们在放a[i]的时候可以放在i - 1后面,这时就是i和j结尾;或者放在i - 1前的任意一个位置j后面,这时就是i - 1和i结尾,特别的,当i是第一个数时加0。
代码:
#include<set> #include<map> #include<stack> #include<cmath> #include<queue> #include<vector> #include<string> #include<cstdio> #include<cstring> #include<sstream> #include<iostream> #include<algorithm> #define P pair<int,int> typedef long long ll; using namespace std; const int maxn = 1000 + 10; const int MOD = 1e9 + 7; const int INF = 0x3f3f3f3f; int dp[maxn][maxn]; //以i和j结尾的最大值 int a[maxn]; int main(){ int n; scanf("%d" ,&n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 2; i <= n; i++){ for(int j = 0; j < i - 1; j++){ a[0] = a[i]; dp[i][j] = max(dp[i][j], dp[i - 1][j] + abs(a[i] - a[i - 1])); dp[i][i - 1] = max(dp[i][i - 1], dp[i - 1][j] + abs(a[i] - a[j])); } } int ans = 0; for(int i = 1; i < n; i++) ans = max(ans, dp[n][i]); printf("%d\n", ans); return 0; }