简单的爱心效果

扑克游戏

描述

有一种别样“小猫钓鱼”扑克游戏。有 N 张牌,每张牌都有一个花色和点数。游戏 的规则:扑克接龙时,若前面有同样花色的牌,你可以将这两张牌连同之间的牌都取走, 得到的分值为取走牌点数之和。这里说的是可以,不是必须。给定扑克接龙的顺序,求 最多的得分。

输入

第一行一个整数 N。

第二行 N 个整数,依次表示 1~N 张牌的花色。

第三行 N 个整数,依次表示 1~N 张牌的点数。

输出

一个整数,为游戏可以得到最大得分。

输入样例 1

7

1 2 1 2 3 2 3

1 4 3 4 3 4 5

输出样例 1

23

提示

数据范围:1<=n<=3000

思路

强行枚举肯定超时,这个就不多说了......

设dp[i]为前i张牌可以取到的的最大得分,最终只需要输出dp[n]即可;

dp[i]的值应该怎么取?

首先要考虑一种特殊情况:第i张牌的花色a[i]有可能是第一次出现的,也就是前面没有与它相同花色的牌,所以可以先让dp[i]=dp[i-1]。

接下来怎么做?重点来了!

由题意得,dp[i]=dp[j-1]+(b[j]+b[j+1]+...+b[i])(1<=j<i),其中对j能取到的每一个值代入,再确定dp[i]能取到的最大值即可。

这里有一个小细节

b[j]+b[j+1]+...+b[i]的值如果直接求和,(有可能不)会出现超时的情况,所以我们可以再输入的时候进行一个求前缀和的操作,最后计算b[i]-b[j-1]的值就可以了

代码

#include<iostream>
using namespace std;
int n,a[3005],b[3005],dp[3005],ans;
int main(){
  ios::sync_with_stdio(0);
  cin>>n;
  for(int i=1;i<=n;i++)
  cin>>a[i];
  for(int i=1;i<=n;i++){
    cin>>b[i];
    dp[i]=b[i];
    b[i]+=b[i-1];
  }
  for(int i=1;i<=n;i++){
    dp[i]=dp[i-1];
    for(int j=1;j<i;j++)
      if(a[j]==a[i])
        dp[i]=max(dp[i],dp[j-1]+b[i]-b[j-1]);
  }
  cout<<dp[n];
  return 0;
}

 

posted @ 2023-03-07 09:16  Light-Chaser  阅读(84)  评论(0编辑  收藏  举报
简单的爱心效果