zoukankan      html  css  js  c++  java
  • jdoj 2171: Grape

    jdoj 2171: Grape

    题意

    题目大意
    一个农场的葡萄架上挂着n串葡萄,若取一个葡萄就会获得与其相应的美味值。对于连续的k串葡萄,最多取b串,最少取a串,
    问能够获得的最大美味值为多少
    数据范围
    n<=10000,0<=a<=b<=k<=10

    分析

    考虑到在选到第i串葡萄时,影响到决策的只有i前面k串葡萄

    f[i] [sta] 表示,考虑完第i串葡萄,后k串葡萄的状态为sta时的最大美味值

    小技巧

    1. 看看n的范围,再想想我们的状态表示,可得,每次转移只需要前一个状态的信息,所以我们可以用i&1表示当前位置,那么(i+1)&1就是下一个位置

    2. 为了方便,不妨将这k串葡萄中的距离i最远的一串葡萄使用最后一个二进制位表示, 这样,我们在状态转移时>>1即可

    只有在a <= cnt[sta] <= b时才考虑转移,转移时状态或上 1<<k,不转移时在合法的时候取最大值即可。

    向前推进max

    /*
    5 3 1 2
    -1 1 2 -2 3
    now_ans = 6
    ans = 9
    */

    #include<cstdio>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    const int N = 11;
    const int MAX = (1<<N)-1;
    #define lowbit (i&-i)
    
    inline int read()
    {
        int x=0,f=1;char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-')f=-1;ch = getchar();}
        while(ch >='0' && ch <='9'){x=(x<<1)+(x<<3)+ch-'0';ch = getchar();}
        return x*f;
    }
    
    int n,k,a,b,sum, max_k;
    int f[2][1<<N], val[10000+9], cnt[1<<N];
      
    int getone(int i) {
        int res = 0;
        while(i) ++res, i -= lowbit;
        return res;
    }
    int getval(int i) {
        int res = 0, pos = 1;
        while(i) {
            if(i&1) res += val[pos];
            i = i>>1, ++pos;
        }
        return res;
    }
      
    void pre() {
        n = read(), k = read(), a = read(), b = read();
        for(int i = 1; i <= n; i++) val[i] = read(), sum += val[i];
        max_k = (1<<k)-1;
        for(int i = 0; i <= max_k; i++) cnt[i] = getone(i);
        for(int i = 0; i <= max_k; i++) if(cnt[i]>=a && cnt[i]<=b) f[k&1][i] = getval(i); 
    }
      
    void solve() {
        for(int i = k; i < n; i++) {//小技巧 
            int o = (i&1), op = (o+1)&1;//o表示当前第一维,op表示下一个第一维 
            memset(f[op], -0x3f, sizeof(f[op]));
            for(int j = 0; j <= max_k; j++) if(cnt[j]>=a && cnt[j]<=b) {
                int tmp1 = (j>>1), tmp2 = ((j|(1<<k))>>1);
                //tmp1表示不选,tmp2表示选 
                if(cnt[tmp1]>=a && cnt[tmp1]<=b) f[op][tmp1] = max(f[op][tmp1], f[o][j]);//不减?
                if(cnt[tmp2]>=a && cnt[tmp2]<=b) f[op][tmp2] = max(f[op][tmp2], f[o][j]+val[i+1]);
            }
        }
        int ans = -2147483646;
        for(int j = 0; j <= max_k; j++) if(cnt[j]>=a && cnt[j]<=b) ans = max(ans, f[n&1][j]);
        printf("%d
    ",ans*2-sum);
    }
    int main() {
        pre();
        solve();
        return 0;
    }
    
  • 相关阅读:
    张季跃 201771010139《面向对象程序设计(java)》第三周学习总结
    实验十二
    201771010142 张燕& 杨蓉庆 实验十一 集合
    实验十 泛型程序设计技术
    第九次实验
    第八次实验
    进度条
    实验七 继承附加实验
    第六次实验
    实验四
  • 原文地址:https://www.cnblogs.com/tyner/p/11642676.html
Copyright © 2011-2022 走看看