Educational Codeforces Round 92 (Rated for Div. 2)B-Array Walk

题意

给你一个序列,你能进行k次操作。其中能进行z次向左操作,但是不能进行连续的向左操作。

思路

转移方程是比较容易想出来的

\(dp[i][j]\)表示在第\(i\)位时进行\(j\)次向左操作。

向右:

\[dp[i][j]=max(dp[i][j],dp[i-1][j]+a[j]) \]

向左:

\[dp[i][j]=max(dp[i][j],dp[i+1][j-1]+a[j]) \]

根据状态转移方程可以定出循环。

然后在循环中判断条件为步数是否小于等于k,然后dp求解,更新ans。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define DOF 0x7f7f7f7f
#define endl '\n'
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(case, x) cout << case << "  : " << x << endl
#define open freopen("ii.txt", "r", stdin)
#define close freopen("oo.txt", "w", stdout)
#define IO                       \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0)
#define pb push_back
using namespace std;
//#define int long long
#define lson rt << 1
#define rson rt << 1 | 1
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<long long, long long> PII;
const int maxn = 1e5 + 10;

ll a[maxn], dp[maxn][6];

void solve(){
    int n, k, z;
    cin >> n >> k >> z;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        dp[i][0] = dp[i - 1][0] + a[i];
        for (int j = 1; j <= z; ++j) dp[i][j] = 0;
    }

    //dp[i][j]=max(dp[i][j],dp[i-1][j]+a[j]);
    //dp[i][j]=max(dp[i][j],dp[i+1][j-1]+a[j]);
    ll ans = dp[k + 1][0];
    for (int j = 1; j <= z;++j){
        for (int i = 1; i <= n;++i){
            if(2*j+i-1<=k){
                dp[i][j] = max(dp[i][j], dp[i - 1][j] + a[i]);
                dp[i][j] = max(dp[i][j], dp[i + 1][j - 1] + a[i]);
            }
            ans = max(dp[i][j], ans);
        }
    }
    cout << ans << endl;
}

int main(){
    int t;cin>>t;
    while(t--){
        solve();
    }

    return 0;
}
posted @ 2020-08-02 23:19  waryan  阅读(59)  评论(0编辑  收藏  举报