zoukankan      html  css  js  c++  java
  • 【题解】APIO2007动物园

      首先一眼感受到这题特别的性质……5个?这么小的,感觉就像是状压。脑补了一下,如果没有环的话应该很好做吧……有环怎么办?5真的很小的,随便乱搞肯定也可以。那就放在外面暴力枚举吧。然后正解就出来了。

      然而这题题面真的有毒吧。说好的不能全部选走?我还多加了一个维度,结果数据里面允许全部取走……然后对于<5的点单独写了个爆搜。代码奇长……大家看看就好吧(以及位运算本人一贯以来又清奇又暴力的脑回路……)

      dp[][][0/1],1代表已经保留了至少一个动物……如果要A掉此题的话把转移那里加上dp[][][0]的就好了。整个namespace Speacial都是特判的点……(虽然数据里面并没有)

    #include <bits/stdc++.h>
    using namespace std;
    #define CNST 32
    #define maxn 10300
    int n, c, tot, fans = 0, dp[maxn][CNST][2];
    int num1[maxn * 5], num2[maxn * 5];
    int lst[6] = {0, 1, 3, 7, 15, 31};
    int fst[6] = {0, 16, 24, 28, 30, 31};
    vector <int> V[maxn];
    
    int read()
    {
        int x = 0;
        char c;
        c = getchar();
        while(c < '0' || c > '9') c = getchar();
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x;
    }
    
    void gmax(int &a, int b)
    {
        a = a > b ? a : b;
    }
    
    void print(int x)
    {
        int a[15], tot = 0;
        a[5] = a[4] = a[3] = a[2] = a[1] = 0;
        while(x)
        {
            a[++ tot] = x & 1;
            x >>= 1;
        }
        for(int i = 5; i; i --)
            printf("%d", a[i]);
        return;
    }
    
    void work(int x, int sum, int opt)
    {
        int tem = 0;
        for(vector <int> :: iterator i = V[x].begin(); i < V[x].end(); i ++)
        {
            int k = *i;
            if((sum & num2[k]) || (num1[k] > (sum & num1[k]))) tem ++;
        }
        dp[x][sum][opt] += tem;
        int k1 = (sum << 1) & (fst[4]), k2 = (((sum << 1) & (fst[4])) | 1);
        gmax(dp[x + 1][k1][opt], dp[x][sum][opt]);
        gmax(dp[x + 1][k2][1], dp[x][sum][opt]);
    }
    
    int Check(int now, int sum)
    {
        int ans = 0;
        for(int i = 1; i <= 4; i ++)
        {
            int a = now, b = sum, t = 0;
            t = a & (lst[5 - i]); t <<= i;
            t |= ((b & (fst[i])) >> (5 - i));
            for(vector <int> :: iterator j = V[i].begin(); j < V[i].end(); j ++)
            {
                int k = *j;
                if((t & num2[k]) || (num1[k] > (t & num1[k]))) ans ++;
            }
        }
        return ans;
    }
    
    int DP(int sum, int opt)
    {
        memset(dp, -1, sizeof(dp));
        int ans = 0;
        dp[5][sum][opt] = 0;
        work(5, sum, opt);
        for(int i = 6; i <= n; i ++)
        {
            int maxx = 0;
            for(int j = 0; j < CNST; j ++)
                for(int k = 0; k <= 1; k ++)
                {
                    if(~dp[i][j][k]) work(i, j, k);
                    maxx = max(maxx, dp[i][j][k]);
                }
        }    
        for(int j = 0; j < CNST; j ++)
        {
            if(dp[n][j][1] == -1) continue;
            int p = Check(j, sum);
            ans = max(ans, p + dp[n][j][1]);
        }
        return ans;
    }
    
    void dfs(int x, int sum)
    {
        if(x == 5)
        {
            sum <<= 1;
            if(sum & (CNST - 1)) fans = max(fans, DP(sum, 1));
            else fans = max(fans, DP(sum, 0));
            sum |= 1;
            fans = max(fans, DP(sum, 1));
            return;
        }
        sum <<= 1;
        dfs(x + 1, sum);
        dfs(x + 1, sum |= 1);
    }
    
    int main()
    {
        n = read(), c = read();
        for(int i = 1; i <= c; i ++)
        {
            int E = read(), F = read(), L = read();
            int id = E + 4; if(id > n) id -= n;
            V[id].push_back(++ tot);
            for(int j = 1; j <= F; j ++) //害怕 
            {
                int x = read(); x = id - x;
                if(x < 0) x += n;
                num1[tot] |= (1 << x); 
            }
            for(int j = 1; j <= L; j ++) //喜欢 
            {
                int x = read(); x = id - x;
                if(x < 0) x += n;
                num2[tot] |= (1 << x);
            }
        }
        dfs(1, 0);
        printf("%d
    ", fans);
        return 0;
    } 
  • 相关阅读:
    debian 中安装GIT
    多核处理器 利用多线程 加速 编译内核 速度
    ubuntu下安装中文输入法(乱码等问题)
    ubuntu 10.04源 更新源列表
    php empty,isset,is_null比较(差异与异同) Leone
    Win 7 各版本的含义 Leone
    Atitit DbServiceV4qb9 数据库查询类库v4 新特性
    Atitit 图像处理之仿油画效果 Oilpaint油画滤镜 水彩画 漫画滤镜 v2
    Atitit 多继承实现解决方案 java c#
    Atitit 基于图片图像 与文档混合文件夹的分类
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/9024871.html
Copyright © 2011-2022 走看看