Codefoces Educational Codeforces Round 92 (Rated for Div. 2) B. Array Walk ( dp / 记忆化搜索 )

链接: B. Array Walk
题意:
给一个数列 ,初始价值为 a[1],每次你可以选择向右走或者向左走,走完获得当前位置的数值,最多向左走 z 次,并且不能连续两次向左走,问走 k 步获得的最大价值。
思路:
dp [ i ][ j ] [ k ] 表示当前走第 i 步,已经向左走了 j 次,当前向左还是向右。然后直接转移就好了,如果当前向右,那上一步既可以向左也可以向右,如果当前向左,那上一步只能向右。还有当前位置为 i - 2 * j + 1.
(1表示向左,0表示向右)

dp[i][j][0] = max(dp[i-1][j][0] ,dp[i-1][j][1]) + a[i - 2 *j +1];
dp[i][j][1] = dp[i-1][j-1][0] + a[i - 2 * j + 1];

代码:


#include 
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
int T,z;
ll n,a[maxn],k,dp[maxn][10][3],ans;
void init(){
    for(int i =0;i<n;i++){
        for(int j=0;j<6;j++){
            dp[i][j][0] = dp[i][j][1] = 0;           
         }
    }
    ans = 0;
}
int main(){
    scanf("%d",&T);
    while(T--){
         scanf("%lld%lld%d",&n,&k,&z);
         init();
         for(int i = 1; i <= n; i++) scanf("%lld",&a[i]);
         dp[0][0][0] = a[1];
         dp[0][0][1] = a[1];
         for(int i = 1; i <= k; i ++){
             for(int j = 0; j <= z; j ++){
                 if(i - 2 * j + 1 <= 0) continue;
                 dp[i][j][0] = max(dp[i-1][j][0] ,dp[i-1][j][1]) + a[i - 2 *j +1];
                 dp[i][j][1] = dp[i-1][j-1][0] + a[i - 2 * j + 1];
             }
         }
         for(int i = 0;i <= z;i ++){
             ans=max(ans,dp[k][i][0]);
             ans=max(ans,dp[k][i][1]);
         }
         printf ("%lld\n",ans);
    }
}


或者记忆化搜索一下,也可以,比 dp 慢一点


#include 
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
int T,z;
ll n,a[maxn],k;
ll dp[maxn][10][3];
void init(){
    for(int i =0;i<n;i++){
        for(int j=0;j<6;j++){
            dp[i][j][0] = dp[i][j][1] = -1;           
         }
    }
}
ll dfs(int v,int pos ,int x,int sta){
   ll ans=-1;
   if(dp[v][x][sta] != -1) return dp[v][x][sta];
   if(v == k) return a[pos];
   
   if(pos == 1) ans = max(ans, dfs(v+1,pos+1,x,1) + a[pos]);
   else  if(pos == n) ans = max(ans, dfs(v+1,pos-1,x-1,0) +a[pos]);
   else  if(x == 0)   ans= max(ans, dfs(v+1,pos+1,x,1) + a[pos] );
   else  if(sta == 0) ans = max(ans, dfs(v+1,pos+1,x,1) + a[pos] );
   else  ans = max(ans, max(dfs(v+1,pos+1,x,1) + a[pos], dfs(v+1,pos-1,x-1,0) +a[pos]));
   dp[v][x][sta] = ans;
   
   return ans;
}
int main(){
    scanf("%d",&T);
    while(T--){
         scanf("%lld%lld%d",&n,&k,&z);
         init();
         for(int i = 1; i <= n; i++) scanf("%lld",&a[i]);
         printf ("%lld\n",dfs(0,1,z,0));
    }
}


你可能感兴趣的:(dp,codeforces)