hdu 4778 Rabbit Kingdom(状态压缩)

题目链接:hdu 4778 Rabbit Kingdom

题目大意:Alice和Bob玩游戏,有一个炉子,可以将S个相同颜色的宝石换成一个魔法石,现在有B个包,每个包里有若干个宝石,给出宝石的颜色。现在由Alice开始,两人轮流选取一个包的宝石放入炉中,每当获得一个魔法石时,可以额外获得一次机会再选一个包放入。两人均按照自己的最优策略,问说最后Alice的魔法石-Bob的魔法石是多少。

解题思路:状态压缩,221,对于每次移动到下一个状态,如果获得的魔法石g非零,则说明下一个状态还是自己在取,则要选择最优的。如果g为0,则说明下一个状态不是自己在取,则要取尽量小的,对应也就是相反数尽量大的。

C++ 记忆化版

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxb = 21;
const int maxn = 1<<21;
const int maxg = 10;
const int INF = 0x3f3f3f3f;

int G, B, S;
int c[maxb+5][maxg], s[maxn+5][maxg];
int v[maxn+5], dp[maxn+5];

void init () {
    int t, a;
    memset(c, 0, sizeof(c));
    memset(v, 0, sizeof(v));

    for (int i = 0; i < B; i++) {
        scanf("%d", &t);
        for (int j = 0; j < t; j++) {
            scanf("%d", &a);
            c[i][a]++;
        }
    }

    for (int i = 0; i < (1<<B); i++) {
        for (int j = 0; j < B; j++) {

            if (i&(1<<j))
                continue;

            int e = i|(1<<j);

            if (v[e])
                continue;

            for (int k = 1; k <= G; k++)
                s[e][k] = (s[i][k] + c[j][k]) % S;
        }
    }
}

int add (int k, int x) {
    int ans = 0;
    for (int i = 1; i <= G; i++)
        ans += (s[k][i] + c[x][i]) / S;
    return ans;
}

int dfs (int u) {

    if (u + 1 == (1<<B))
        return 0;

    if (v[u])
        return dp[u];

    int up = -INF;
    int lower = INF;

    for (int i = 0; i < B; i++) {
        if (u&(1<<i))
            continue;

        int g = add (u, i);

        if (g)
            up = max(up, dfs(u|(1<<i))+g);
        else
            lower = min(lower, dfs(u|1<<i));
    }
    v[u] = 1;
    return dp[u] = max(up, -lower);
}

int main () {
    while (scanf("%d%d%d", &G, &B, &S) == 3 && G + B + S) {
        init();
        memset(v, 0, sizeof(v));
        printf("%d\n", dfs(0));
    }
    return 0;
}
C++ 递推版

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxb = 21;
const int maxn = 1<<21;
const int maxg = 10;
const int INF = 0x3f3f3f3f;

int G, B, S;
int c[maxb+5][maxg], s[maxn+5][maxg];
int v[maxn+5], dp[maxn+5];

void init () {
    int t, a;
    memset(c, 0, sizeof(c));
    memset(v, 0, sizeof(v));

    for (int i = 0; i < B; i++) {
        scanf("%d", &t);
        for (int j = 0; j < t; j++) {
            scanf("%d", &a);
            c[i][a]++;
        }
    }

    for (int i = 0; i < (1<<B); i++) {
        for (int j = 0; j < B; j++) {

            if (i&(1<<j))
                continue;

            int e = i|(1<<j);

            if (v[e])
                continue;

            for (int k = 1; k <= G; k++)
                s[e][k] = (s[i][k] + c[j][k]) % S;
        }
    }
}

int add (int k, int x) {
    int ans = 0;
    for (int i = 1; i <= G; i++)
        ans += (s[k][i] + c[x][i]) / S;
    return ans;
}

int solve () {
    int e = (1<<B) - 1;
    memset(dp, -INF, sizeof(dp));
    dp[e] = 0;

    for (int u = e; u >= 0; u--) {

        for (int i = 0; i < B; i++) {
            if ((u&(1<<i)) == 0)
                continue;

            int ui = u-(1<<i);
            int g = add(ui, i);

            if (g)
                dp[ui] = max(dp[ui], dp[u] + g);
            else
                dp[ui] = max(dp[ui], -dp[u]);
        }
    }
    return dp[0];
}

int main () {
    while (scanf("%d%d%d", &G, &B, &S) == 3 && G + B + S) {
        init();
        printf("%d\n", solve());
    }
    return 0;
}

hdu 4778 Rabbit Kingdom(状态压缩)

时间: 2024-08-28 21:06:42

hdu 4778 Rabbit Kingdom(状态压缩)的相关文章

hdu 4778 Gems Fight!(状态压缩DP)

又是一道状态压缩,刚开始老是往博弈的方法想,总是没思路. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=21; const int inf=0x3f3f3f3f; int g,n,s; int sum[1<<N]; int res[10]; int c[22][10]; i

hdu 4057 AC自动机+状态压缩dp

http://acm.hdu.edu.cn/showproblem.php?pid=4057 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for them. 2012 is coming, and Dr. X wants to take some rabbits to Noah's Ark, or there are no rabbits any more.

hdu 3217 Health(状态压缩DP)

Health Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 527    Accepted Submission(s): 145 Problem Description Unfortunately YY gets ill, but he does not want to go to hospital. His girlfriend LM

hdu 4777 Rabbit Kingdom(树状数组)

题目链接:hdu 4777 Rabbit Kingdom 题目大意:一个兔子王国,有N只兔子,每只兔子有一个重量,如果两只兔子的重量不互质,那么就会干架,现在国王想将l r之间的兔子关进监狱,它想知道会有多少只兔子不会和别的兔子干架. 解题思路:预处理出每只兔子的L,R表示向左和向右最近会与该兔子发生冲突的兔子,预处理的时候只要将每只兔子的重量分解成质因子后遍历两遍. 对于询问,将询问按照右区间排序,碰到i,则L位置+1,碰到R,则i位置+1,L位置-1.(如果L ≤ l && r ≤ R

HDU 1885 Key Task 状态压缩+搜索

点击打开链接 Key Task Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1176    Accepted Submission(s): 462 Problem Description The Czech Technical University is rather old - you already know that it c

hdu 4856 Tunnels(bfs+状态压缩)

题目链接:hdu 4856 Tunnels 题目大意:给定一张图,图上有M个管道,管道给定入口和出口,单向,现在有人想要体验下这M个管道,问最短需要移动的距离,起点未定. 解题思路:首先用bfs处理出两两管道之间移动的距离,然后后用状态压缩求出最短代价,dp[i][j],i表示的已经走过的管道,j是当前所在的管道. #include <cstdio> #include <cstring> #include <queue> #include <algorithm&g

hdu 4352 数位dp + 状态压缩

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2265    Accepted Submission(s): 927 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful

HDU 4921 Map DFS+状态压缩+乘法计数

算最多十条链,能截取某前缀段,每种方案都可以算出一个权值,每种方案的概率都是总数分之一,问最后能构成的所有可能方案数. 对计数原理不太敏感,知道是DFS先把链求出来,但是想怎么统计方案的时候想了好久,其实因为只能取某个链的前缀,所以直接取链长加+1 然后相乘即可,当然因为会出现都是空的那种情况,要去掉,全部乘完之后,要-1 然后就是算权值了,权值等于当前加进来的点的总和 以及 等级相同的点的加成,并不是特别好算,这时候考虑每个状态下的点对全局的贡献,对,就是这个思想,用状态压缩来表示状态,然后这

HDU 1557 权利指数 状态压缩 暴力

HDU 1557 权利指数 状态压缩 暴力 ACM 题目地址:HDU 1557 权利指数 题意: 中文题,不解释. 分析: 枚举所有集合,计算集合中的和,判断集合里面的团体是否为关键团队. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: 1557.cpp * Create Date: 2014-06-28 14:47:58 * Descripton: brute force/ set */ #include <cstdio&g