AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

The Karting

作者: 作者的头像   清风qwq ,  2024-11-01 21:10:31 ,  所有人可见 ,  阅读 62


2


原题链接

思路

设 $s_i$ 表示从 $1$ 到 $i$ 路径的长度。

假设端点序列的第一个点为回路的起点。

对于一个端点,若没有改变方向,那么我们暂时删除它,于是我们得到一个新的端点序列。

设奇数位为左括号,偶数位为右括号,于是总贡献相当于 $\sum_{i=1}^m (-1)^i 2 s_i + a_0$。

设 $f_{i,j,k}$ 表示前 $i$ 个点里有 $j$ 个端点,且共有 $k$ 个左括号为匹配的情况下最大难度。

发现端点一定是括号匹配,且不存在一个前缀使得其能被括号匹配,于是有转移方程:

upd(f[i][j][k], f[i - 1][j][k]); // 不是端点
if (k > 0) upd(f[i][j][k], f[i - 1][j - 1][k]); // 路过
if (k > 1) upd(f[i][j][k], f[i - 1][j - 1][k - 1] + x - s[i] * 2); // 左括号端点
upd(f[i][j][k], f[i - 1][j - 1][k + 1] + x + s[i] * 2); // 右括号端点

注意到题目需要恰好为 $m$,需要考虑路过一个点不转向的情况。

时间复杂度 $O(n^3)$,重点在于将路径问题转化为括号匹配。

另:

好像大部分题解被我hack了:
In

4 4
0 10 -100 10

Out

-160

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int N = 110;
int f[N][N][N];

void upd(int &x, int y) {
    x = (x < y) ? y : x;
}

int main() {
    int n, m, x;
    while (~scanf("%d%d%d", &n, &m, &x)) {
        vector<int> a(n + 10), s(n + 10);
        for (int i = 1; i < n; i ++ ) {
            scanf("%d", &a[i]);
            s[i + 1] = s[i] + a[i];
        }
        memset(f, 0xc0, sizeof f);
        for (int i = 1; i <= n; i ++ ) {
            f[i][0][0] = 0;
            f[i][1][1] = x - s[i] * 2;
            for (int j = 1; j <= i; j ++ ) 
                for (int k = 0; k <= i; k ++ ) {
                    upd(f[i][j][k], f[i - 1][j][k]);
                    if (k > 0) upd(f[i][j][k], f[i - 1][j - 1][k]);
                    if (k > 1) upd(f[i][j][k], f[i - 1][j - 1][k - 1] + x - s[i] * 2);
                    upd(f[i][j][k], f[i - 1][j - 1][k + 1] + x + s[i] * 2);
                }
        }
        printf("%d\n", f[n][m][0]);
    }
    return 0;
}

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息