Hướng dẫn giải của Phần thưởng


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Gọi ~dp (l , r , k)~ là gtri lớn nhất nếu đã xét các số trong đoạn từ ~l - > r~ và đã chọn ~k~ cặp số. Gọi giá trị tại vị trí ~i~ là ~a[i]~.

  • Với thao tác 1 ~dp (l , r , k)~ lấy max với ~dp (l + 2, r , k - 1)~ + ~|a[l]| - |a[l + 1]|~;
  • Với thao tác 2 ~dp (l , r , k)~ lấy max với ~dp (l, r - 2 , k - 1)~ + ~|a[r]| - |a[r - 1]|~;

  • Với thao tác 3 ~dp (l , r , k)~ lấy max với ~dp (l + 1, r - 1 , k - 1)~ + ~|a[l]| - |a[r]|~;

  • Với thao tác 4 ~dp (l , r , k)~ lấy max với ~dp (l + 1, r , k)~;

  • Với thao tác 5 ~dp (l , r , k)~ lấy max với ~dp (l, r - 1 , k)~;

Để dễ dàng cài đặt, ta sẽ sử dụng đệ quy có nhớ.

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k;
const int N = 307;
int a[N];
int f[N][N][N];
const int inf = 1e18;
int cal (int l, int r, int x) {
    if (f[l][r][x] != -inf) return f[l][r][x];
    if (x == 0) return 0;
    if (l >= r) {
        return -inf; 
    }
    int res = -inf;
    if (r-1 >= l){
        res = max (res,cal(l+2,r,x-1)+abs(a[l+1]-a[l]));
        res = max (res,cal(l,r-2,x-1)+abs(a[r]-a[r-1]));
        res = max (res,cal(l+1,r-1,x-1)+abs(a[r]-a[l]));
    }
    res = max (res,cal(l+1,r,x));
    res = max (res,cal(l,r-1,x));
    return f[l][r][x] = res;
}
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> k;
    for (int i=0; i<=n+2; i++) {
        for (int j=0; j<=n+2; j++) {
            for (int c=0; c<=k+2; c++) f[i][j][c] = -inf;
        }
    }
    for (int i=1; i<=n; i++) {
        cin >> a[i];
    }
    cout << cal (1,n,k);
}