zoukankan      html  css  js  c++  java
  • 暑假第二十三测

    题解:

    第一题:

    贪心

    状压:我们发现110,100这样一列有两个1的一定不会组合,就算他们和后面凑成了0,那么其中一个必定可以和后面的构成0,所以我们不考虑他们的转移;

    而0和1组合和0和0组合是等价的,因为我们不考虑一列两个1,所以i+ j ==> i&j, 最后看是否转移为0;

     

    #include<bits/stdc++.h>
    using namespace std;
    const int M = (1 << 4) + 10; 
    bool dp[2][M];
    int ww[M][M], w[M][M], zw[M][M], a[5];
    
    inline int get(int m){
        if(m == 1)return a[1];
        if(m == 2)return (a[1]<<1) + a[2];
        if(m == 3)return (a[1]<<2) + (a[2]<<1) + a[3];
        return (a[1]<<3) + (a[2]<<2) + (a[3]<<1) + a[4];
    }
    void init(){
        memset(ww, -1, sizeof(ww));
        memset(w, -1, sizeof(w));
        memset(zw, -1, sizeof(zw));
        for(int i = 0; i < (1 << 2); i++){
            for(int j = 0; j < (1 << 2); j++){
                bool fg = 0;
                for(int k = 0; k < 2; k++){ 
                    if(((1<<k) & i) && ((1 << k) & j))fg = 1;    
                }if(!fg)ww[j][i] = i & j;
            }
                
            
        }
        for(int i = 0; i < (1 << 3); i++){
            for(int j = 0; j < (1 << 3); j++){
                bool fg = 0;
                for(int k = 0; k < 3; k++){ 
                    if(((1<<k) & i) && ((1 << k) & j))fg = 1;    
                }if(!fg)zw[j][i] = i & j;
            }
                
            
        }
        
        for(int i = 0; i < (1 << 4); i++){
            for(int j = 0; j < (1 << 4); j++){
                bool fg = 0;
                for(int k = 0; k < 4; k++){ 
                    if(((1<<k) & i) && ((1 << k) & j))fg = 1;    
                }if(!fg)w[j][i] = i & j;
            }
                
            
        }
    }
    
    int main(){
        freopen("prob.in","r",stdin);
        freopen("prob.out","w",stdout);
        int t, tt = 0;
        scanf("%d", &t);
        init();
        while(t--){
            int n, m, now = 0;
            bool fg = 0;
            scanf("%d%d", &n, &m);
            memset(dp, 0, sizeof(dp));
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++)scanf("%d", &a[j]);
                if(fg)continue;
                int s = get(m);
                now ^= 1;
                dp[now][s] = 1;
                if(m == 1){
                    if(!s)fg = 1;
                }
                else if(m == 4)
                    for(int sc = 0; sc < (1 << 4); sc++){
                        if(dp[now^1][sc]){
                            dp[now][sc] = 1;
                            if(w[s][sc] != -1)dp[now][w[s][sc]] = 1;
                        }
                    }
                else if(m == 2){
                    for(int sc = 0; sc < (1 << 2); sc++){
                        if(dp[now^1][sc]){
                            dp[now][sc] = 1;
                            if(ww[s][sc] != -1)dp[now][ww[s][sc]] = 1;
                        }
                    }
                }
                else {
                    for(int sc = 0; sc < (1 << 3); sc++){
                        if(dp[now^1][sc]){
                            dp[now][sc] = 1;
                            if(zw[s][sc] != -1)dp[now][zw[s][sc]] = 1;
                        }
                    }
                }
                if(dp[now][0])fg = 1;
                //if(fg)cout<<i<<"KKKKKKKK";
                
            }
            //printf("%d %d %d ",++tt, n, m);
            fg ? puts("YES") : puts("NO"); 
        }
    }
    View Code

    第二题:贪心

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 1e5 + 10;
    #define ll long long
    int n;
    struct pp{ll s,a,b; int id;}st1[M], st2[M], p[M];
    ll sum[2], tot[2], yp[2];
    bool cmp(pp T, pp C){
        return T.a - T.b > C.a - C.b;
    }
    bool cmp2(pp T, pp C){
        return T.b - T. a > C.b - C.a;
    }
    int main()
    {
        freopen("pizza.in","r",stdin);
        freopen("pizza.out","w",stdout);
           ll totm = 0, SS;
        scanf("%d%I64d", &n, &SS);
        for(int i = 1; i <= n; i++){
            scanf("%I64d%I64d%I64d", &p[i].s, &p[i].a, &p[i].b);
            p[i].id = i;
            if(p[i].a >= p[i].b)st1[++tot[1]] = p[i], sum[1] += p[i].s * p[i].a, yp[1] += p[i].s;
            else st2[++tot[2]] = p[i], sum[2] += p[i].s * p[i].b, yp[2] += p[i].s;
            totm += p[i].s;
        }
        sort(st1 + 1, st1 + 1 + tot[1], cmp);
        sort(st2 + 1, st2 + 1 + tot[2], cmp2);
        
        
        ll cas1, cas2;
        cas1 = cas2 = sum[2] + sum[1];
        ll ned = ceil(1.0*totm / SS);
        ll h1 = ceil(1.0*yp[1] / SS);
        ll h2 = yp[2] - (ned - h1) * SS;
        int pw = tot[2];
        while(h2 > 0){
            if(h2 < st2[pw].s) {
                cas1 -= (st2[pw].b - st2[pw].a) * h2;
                h2 = 0;
            }
            else {
                cas1 -= (st2[pw].b - st2[pw].a) * st2[pw].s;
                h2 -= st2[pw].s;
            }
            pw--;
        }
        h2 = yp[1] - (h1 - 1) * SS;
        pw = tot[1];
        while(h2 > 0){
            if(h2 < st1[pw].s) {
                cas2 -= (st1[pw].a - st1[pw].b) * h2;
                h2 = 0;
            }
            else {
                cas2 -= (st1[pw].a - st1[pw].b) * st1[pw].s;
                h2 -= st1[pw].s;
            }
            pw--;
        }    
        printf("%I64d
    ", max(cas1, cas2));
        
    }
    View Code

    第三题:线段树优化dp

    对于c(k,i)的修改,我们只需要记录一个lst的数组,那么他就制度lst + 1 到i有贡献;

    #include<bits/stdc++.h>
    using namespace std;
    
    const int M = 20000 + 5, inf = 1e9;
    int n, m, pre[M], a[M], pos[M], dp[2][M];
    struct Node{
        Node *ls, *rs;
        int v, tag;
        void up(){
            v = max(ls->v , rs->v);
        }
        
        void down(){
            if(tag){
                ls->tag += tag; rs->tag += tag;
                ls->v += tag; rs->v += tag;
                tag = 0;
            }
        }
    }pool[M << 2], *root, *tail = pool;
    
    
    #define Ls nd->ls, lf, mid
    #define Rs nd->rs, mid + 1, rg
    int query(int L, int R, Node *nd = root, int lf = 1, int rg = n){    
        if(L <= lf && rg <= R)return nd->v;
        nd->down();
        int mid = (lf + rg) >> 1;
        int v = -inf;    
        if(L <= mid)v = query(L, R, Ls);
        if(R > mid)v = max(v, query(L, R, Rs));
        return v;
    }
    void modify(int L, int R, int val, Node *nd = root, int lf = 1, int rg = n){
        if(L <= lf && rg <= R){
            nd->v += val; nd->tag += val;
            return ;
        } 
        nd->down();
        int mid = (lf + rg) >> 1;
        if(L <= mid)modify(L, R, val, Ls);
        if(R > mid)modify(L, R, val, Rs);
        nd->up();
    }
    
    Node *build(int vin, int lf = 1, int rg = n){
        Node *nd = ++tail;
        if(lf == rg)nd->v = dp[vin][lf], nd->tag = 0;
        else {
            int mid = (lf + rg) >> 1;
            nd->ls = build(vin, lf, mid);
            nd->rs = build(vin, mid + 1, rg);
            nd->tag = 0;
            nd->up();
        }
        return nd;
    }
    
    int main(){ 
        freopen("scream.in","r",stdin);
        freopen("scream.out","w",stdout);
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
        for(int i = 1; i <= n; i++){
            pre[i] = pos[a[i]];
            pos[a[i]] = i;
        }
        int now = 0, lst = 1;
        for(int i = 1; i <= n; i++)dp[lst][i] = dp[lst][i - 1] + (pre[i] == 0);
        for(int k = 2; k <= m; k++){
            tail = pool;
            root = build(lst);
            for(int i = 1; i <= n; i++){
                if(i < k)dp[now][i] = -inf;
                else {
                    modify(max(pre[i], 1), i - 1, 1);
                    dp[now][i] = query(1, i - 1);
                }
            }
            swap(now, lst);
        }
        printf("%d
    ", dp[lst][n]);
    }
    View Code

    今天前两道题都是贪心,我却一直在想dp, 贪心还是太烂了, 必须要加强重视了;

  • 相关阅读:
    Assembly之instruction之CMP
    Assembly之Instruction之Byte and Word
    MSP430之section(1)
    MSP430之software development flow
    openMSP430之Custom linker script
    CDC之Synchronizers
    CDC之Metastability
    Embedded之Stack之三
    Embedded之Stack之二
    Embedded之Stack之一
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9526624.html
Copyright © 2011-2022 走看看