2023牛客暑期多校训练营2-K--Box(线性DP)

题目描述

That's enough. There's no need to bring Genshin Impact into every little matter. Genshin Impact hasn't done anything to offend or harm you. Why do you keep mindlessly bashing it? miHoYo puts a lot of effort into promoting Chinese culture through their games, and all you do is sit behind a keyboard and criticize a conscientious company. People like you are ruining the future of Chinese games.

Now, the Traveler has n boxes in their possession, some of which have lids that can be shifted left or right by at most one step. If the i-th box is covered with a lid, you gain ai score.(Covering it with multiple lids still gets only ai score.) Determine the maximum total game score achievable by covering boxes with lids after shifting serveral(possibly, zero) lids.

输入描述:

The first line contains a integer, n(1≤n≤10^6), representing the number of boxes.

The second line contains n integers, where the i-th integer ai (0≤ai≤10^9) represents the value of i-th box.

The third line contains n integers, where the i-th integer bi​ (0≤bi≤1) represents whether i-box has a lid. bi=0 means there is no lid on the box.

输出描述:
An integer represents the answer.

输入1:

3
1 2 3
0 1 0

输出1:

3

输入2:

3
1 3 1
1 0 1

输出2:

4

题意:有n个盒子,第二行表示每个盒子的价值,第三行表示第i个位置有无盖子,1表示有盖子,0表示没有盖子,被盖住的盒子,你会获得它的价值,对于每个盖子,最多向左或者右移动一格,问总的价值之和最大值是多少。

解析:我们可以设DP[ i ][ j ]表示前 i 个盖子,状态为 j 时的最大价值,j为0,1,2分别表示这个盖子,往左,不动,往右,然后我们每次由第i-1个盖子转移过来即可。

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
typedef long long ll;
ll a[N],dp[N][3];
int b[N];
void solve()
{
    int n,cnt=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        if(x) b[++cnt]=i;//存每个盖子的位置
    }
    if(!cnt)//如果没有盖子,直接输出退出即可
    {
        printf("0\n");
        return;
    }
    if(b[1]>1) dp[1][0]=a[b[1]-1];//判断边界,先初始化第一个盖子
    if(b[1]<n) dp[1][2]=a[b[1]+1];
    dp[1][1]=a[b[1]];
    for(int i=2;i<=cnt;i++)
    {
        for(int j=0;j<3;j++)//第i-1个盖子的状态
        {
            for(int k=0;k<3;k++)//第i个盖子的状态
            {
                int pos1=b[i-1]+j-1;//第i-1个盖子的位置
                int pos2=b[i]+k-1;//第i个盖子的位置
                if(pos1>=1&&pos1<=n&&pos2>=1&&pos2<=n)//防止出界
                {
                    if(pos1<pos2)//第i-1个只能在第i个的左边
                    {
                        dp[i][k]=max(dp[i][k],dp[i-1][j]+a[pos2]);
                    }
                }
            }
        }
    }
    printf("%lld\n",max({dp[cnt][0],dp[cnt][1],dp[cnt][2]}));//三种状态取max即是答案
}
int main()
{
    // freopen("input.txt","r",stdin);
    // freopen("output.txt","w",stdout);
    int t=1;
    //scanf("%d",&t);
    while(t--) solve();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值