• 牛客练习赛6 珂学送分2


    链接:https://ac.nowcoder.com/acm/contest/26/E
    来源:牛客网

    题目描述

    珂...珂...珂朵莉给你出了一道送分题:

    给你一个长为n的序列{vi},和一个数a,你可以从里面选出最多m个数

    一个合法的选择的分数定义为选中的这些数的和加上额外规则的加分:

    有b个额外的规则,第i个规则即为:

    对于这个序列的所有长为a的连续子区间,如果这个子区间中对应的给出的xi个位置都被选中了,则这次选择的分数加上yi(yi可能为负数,这种情况下分数仍然要加上y)

    输入描述:

    第一行四个数n,m,a,b

    之后一行n个数表示序列v

    之后表示b个规则

    每个规则先输入两个数xi和yi

    之后一行xi个数,分别表示这给定的xi个位置

    输出描述:

    一行一个数表示最大可能得到的分数
    示例1

    输入

    复制
    5 3 3 1
    2 3 3 3 3
    2 233
    1 3

    输出

    复制
    474

    说明

    示例2

    输入

    复制
    5 3 3 1
    111 222 333 444 555
    2 52
    1 3

    输出

    复制
    1384

    说明

    备注:

    对于100%的数据,0 <= n <= 100 , 0 <= m <= 50 ,0
    <= a <= 16 , 0 <= b <= 100000, 所有出现的数的绝对值<=
    600

    解题思路:
    首先预处理出每个状态下能得到的额外的分数,定义状态dp【i】【j】【k】为前i个数中取j个数,最后a个数的状态为k时的最大分数,那么状态转移方程为:取当第i+1个数字时:
    dp[1^flag][j+1][(k>>1)|(1<<(a-1))]=max(dp[1^flag][j+1][(k>>1)|(1<<(a-1))],dp[flag][j][k]+eval[(k>>1)|(1<<(a-1))]+val[i]);
    不取第i+1个数字:dp[1^flag][j][k>>1]=max(dp[1^flag][j][k>>1],dp[flag][j][k]+eval[k>>1]);
    这里我用了滚动数组。
    #include<bits/stdc++.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    int eval[1<<16];
    int val[105];
    int dp[2][55][1<<16];
    int main(){
        int n,m,a,b;
        scanf("%d%d%d%d",&n,&m,&a,&b);
        for(int i=0;i<n;i++){
            scanf("%d",&val[i]);
        }
        for(int i=0;i<b;i++){
            int x,y;
            int tem=0;
            int tet;
            scanf("%d%d",&x,&y);
            while(x--){
                scanf("%d",&tet);
                tet--;
                tem=tem|(1<<tet);
            }
            eval[tem]+=y;
        //    cout<<tem<<endl;
        } 
        for(int i=(1<<a)-1;i>=0;i--)
        {
            if(eval[i]!=0)
            {
                int j=(1<<a)-1-i;
                for(int s=j;s>0;s=(s-1)&j)
                    eval[i|s]+=eval[i];
            }
        }
        for(int i=0;i<=m;i++){
            for(int j=0;j<(1<<a);j++){
                dp[0][i][j]=-inf;
            }
        }
            for(int j=0;j<(1<<a);j++){
                int tem=0;
                int cnt=0;
                for(int k=0;k<a;k++){
                    if(j&(1<<(k))){
                        tem+=val[k];
                        cnt++;
                    }
                }
                dp[0][cnt][j]=max(dp[0][cnt][j],tem+eval[j]);
            }
            int flag=0;
            for(int i=a;i<n;i++){
                for(int j=0;j<=m;j++){
                    for(int k=0;k<(1<<a);k++){
                        dp[1^flag][j][k]=-inf;
                    }
                }
                for(int j=0;j<=m;j++){
                    for(int k=0;k<(1<<a);k++){
                    //    int sta=k;
                    if(dp[flag][j][k]==-inf)continue;
                        int tem=(k>>1)|(1<<(a-1));
                        dp[1^flag][j][k>>1]=max(dp[1^flag][j][k>>1],dp[flag][j][k]+eval[k>>1]);
                        dp[1^flag][j+1][tem]=max(dp[1^flag][j+1][tem],dp[flag][j][k]+eval[tem]+val[i]);
                    }
                }
                flag=flag^1;
            }
            int ans=-inf;
            for(int i=0;i<=m;i++){
                for(int j=0;j<(1<<a);j++){
                    ans=max(ans,dp[flag][i][j]);
                }
            }
            printf("%d
    ",ans);
            
        return 0;
    }
  • 相关阅读:
    Java子类和父类之间方法和属性关系
    静态链接库与动态链接库
    两人相遇问题时间段
    try catch finally
    shell判断条件参数过多
    python C++ Java 文件数据库等流操作,当打开后必须关闭
    CSS3 target 伪类不得不说那些事儿(纯CSS实现tab切换)
    清浮动方法
    this函数的理解
    css3 tranform  transition animation
  • 原文地址:https://www.cnblogs.com/Zhi-71/p/11503875.html
Copyright © 2020-2023  润新知