zoukankan      html  css  js  c++  java
  • 牛客练习赛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;
    }
  • 相关阅读:
    nyoj 311 完全背包
    HDU 1864 最大报销额
    HDU 1087 Super Jumping! Jumping! Jumping! 最长递增子序列(求可能的递增序列的和的最大值) *
    HDU 2602 Bone Collector
    1014 装箱问题 CODE[VS]
    JOBDU 1140 八皇后
    POJ 1979 Red and Black
    POJ 1129 Channel Allocation
    HDU 1863 畅通工程
    第二百四十七天 how can I 坚持
  • 原文地址:https://www.cnblogs.com/Zhi-71/p/11503875.html
Copyright © 2011-2022 走看看