文远知行杯广东工业大学第十六届程序设计竞赛 I V字钩爪

23 篇文章 2 订阅

V字钩爪

题目链接
在这里插入图片描述
我们首先的想法是想把相互独立的点分开,把会产生影响的点放一起,那么哪些是会产生影响的点呢。这里是相隔 k k k 即可产生相互影响,那实际上就是处在 k k k 的一个同余系下的点就是会产生影响的,我们可以把处在同一同余系下的点如下代码拆出来扔进一个 v e c t o r vector vector 里面去,于是我们就可以独立考虑每个同余系的答案。

for (int i = 1; i <= n; ++i) {
    g[i % k].push_back(a[i]);
}

那么对于同一个 i % k i\% k i%k (同余系),他们的值如何算呢,实际上他们的限制就是一次操作只能取相邻的两个点,那么我们可以通过 d p dp dp 解决这个问题。

我们设 d p [ i ] [ 0 / 1 ] dp[i][0/1] dp[i][0/1] 为考虑到了第 i i i 个物品(下标从 0 0 0 开始),且第 i i i 个物品不取 ( 0 ) (0) (0) 或者取 ( 1 ) (1) (1) 情况下所能得到的最大值。

我们这里设第 i i i 个物品价值为 v a l [ i ] val[i] val[i] ,且当前同余系下共有 m m m 个物品,那么我们有:
d p [ 0 ] [ 0 ] = d p [ 0 ] [ 1 ] = 0 dp[0][0]=dp[0][1]=0 dp[0][0]=dp[0][1]=0
d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] )   ( i > 0 ) dp[i][0] = max(dp[i - 1][0], dp[i-1][1])\ (i>0) dp[i][0]=max(dp[i1][0],dp[i1][1]) (i>0)
d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] + v a l [ i − 1 ] + v a l [ i ]   ( i > 0 ) dp[i][0] = dp[i - 1][0]+val[i-1]+val[i]\ (i>0) dp[i][0]=dp[i1][0]+val[i1]+val[i] (i>0)

最终 m a x ( d p [ m − 1 ] [ 0 ] , d p [ m − 1 ] [ 1 ] ) max(dp[m-1][0], dp[m-1][1]) max(dp[m1][0],dp[m1][1]) 为这一同余系的答案,最后我们把每种情况求和即是最终答案。

#include <bits/stdc++.h>
#define lson (rt<<1)
#define rson ((rt<<1)|1)

using namespace std;

typedef long long ll;

const int N = 1e6 + 10;

int n, k, a[N], vis[N];
ll dp[N][2];
vector<int> g[N];

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    for (int i = 1; i <= n; ++i) {
        g[i % k].push_back(a[i]);
    }
    ll ans = 0;
    for (int i = 0; i < k; ++i) {
        if (g[i].empty()) continue;
        int m = (int)g[i].size();
        for (int j = 1; j < m; ++j) {
            dp[j][0] = max(dp[j - 1][0], dp[j - 1][1]);
            dp[j][1] = dp[j - 1][0] + g[i][j] + g[i][j - 1];
        }
        ans += max(dp[m - 1][0], dp[m - 1][1]); 
    }
    cout << ans << endl;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值