队内赛 T3区间DP大哥扛纵连
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了队内赛 T3区间DP大哥扛纵连相关的知识,希望对你有一定的参考价值。
队内赛 T3 大哥扛纵连
题目
输入输出样例
输入 #1
4 2
2 4 3 5
1 3
2 4
输出 #1
10
12
输入 #2
15 10
10 71 84 33 6 47 23 25 52 64 70 31 22 31 2
6 11
4 8
1 14
9 13
1 1
2 4
8 14
2 14
11 13
2 2
输出 #2
281
180
828
263
10
201
364
744
123
71
大样例 #3
example3.zip
为什么这个题目背景这么熟悉。
解题思路
设 f[i][j] 为 i 到 j 的山聚头的最小花费
如果聚头的山在最高山左边,那么T右边的山就需要花费 T_hight * (j -T + 1),T 左边的山花费 f[i][T - 1]
f[i][j] = f[i][T - 1] + T_hight * (j -T + 1)
如果聚头的山在 T 右边,f[i][j] = f[T + 1][j] + T_hight * (T - i + 1)
取个max就好了,最后 O(1) 查询 f[l][r] 就好了
Code
#include <bits/stdc++.h>
using namespace std;
struct DT{
int i, s;
}mx[2010][2010];
int n, m, a[2100], f[2100][2100];
int main() {
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i ++)
scanf("%d", &a[i]);
for(int i = 1; i <= n; i ++) {
mx[i][i].s = a[i], mx[i][i].i = i;
for(int j = i + 1; j <= n; j ++)
if(a[j] > mx[i][j - 1].s) { //O(N ^ 2)记录 i 到 j 的最高山是哪座(T),高度是多少(T_hight)
mx[i][j].s = a[j];
mx[i][j].i = j;
} else {
mx[i][j].s = mx[i][j - 1].s;
mx[i][j].i = mx[i][j - 1].i;
}
}
for(int i = 1; i <= n; i ++)
f[i][i] = a[i]; //自己跳自己也要距离😅
for(int len = 2; len <= n; len ++)
for(int i = 1; i <= n; i ++) {
int j = i + len - 1, k = mx[i][j].i;
f[i][j] = min(f[i][k - 1] + a[k] * (j - k + 1), f[k + 1][j] + a[k] * (k - i + 1));
}
for(int i = 1; i <= m; i ++) {
int l, r;
scanf("%d %d", &l, &r);
printf("%d\\n", f[l][r]);
}
}
以上是关于队内赛 T3区间DP大哥扛纵连的主要内容,如果未能解决你的问题,请参考以下文章