题解:AT_abc267_d - Index × A(Not Continuous ver.)
TigerTanWQY · · 题解
题意
给定一个长度为
求长度为
思路
一眼 DP。先观察条件:
- 序列长度;
- 已选元素个数;
- 序列的权值。
设计状态
显然,No.3 是我们要求的东西,而 No.1、No.2 缺一不可,且已知 No.1 和 No.2 就很容易推出 No.3,所以状态可以这样设计:
状态转移
比较显然(由题易知)。
// 状态转移
memset(f, -0x3f, sizeof(f));
for(int i = 1; i <= n; ++i) {
f[i][1] = a[i]; // 初始状态
for(int j = 1; j < i; ++j)
for(int k = 1; k <= j && k < m; ++k)
if(f[j][k] != -0x3f3f3f3f3f3f3f3f)
f[i][k + 1] = max(f[i][k + 1], f[j][k] + a[i] * (k + 1));
}
注意到循环 for 的结束条件为 k <= j && k < m。其中 k < m 表示子序列长度不能超过 k <= j 是优化(很重要) ,表示已选元素不能超过
这样可以带来约 你可以试着删掉优化,然后就会喜提 TLE。
分析一下时间复杂度,易知为
答案状态
// 答案状态
long long ans = -0x3f3f3f3f3f3f3f3f;
for(int i = 1; i <= n; ++i)
ans = max(ans, f[i][m]);
cout << ans << endl;
为什么不是
完整代码
link
时间有点极限
总结
- 这是一道 DP 好题;
- 肯定有优化,但这是最容易想到的 DP 思路,且可以 AC;
- 重点在于转移部分的优化,很好理解,也很有用;
- 蒟蒻的第 3 篇题解,如有疏漏请多指教;
- 看完了,记得点个赞哦!
Update
- “状态转移”中分析时间复杂度时,原始计算量应为
8\times 10^9 ,而非8\times 10^8 。——感谢 @zbbfans