HDU 4778 Gems Fight!(dp)

HDU 4778 Gems Fight!

题目链接

题意:有n个背包,包里有一些宝石,现在爱丽丝和你轮流选背包,把包里宝石丢到锅中,然后如果锅中有宝石数量到s个,就会得到魔法石,并且可以继续选背包,两人都按最优策略去取,问最后两人魔法石会差多少。

思路:dp,dp[s]表示选背包状态为s时候的值,然后去记忆化搜索即可,注意如果当前生成魔法石就继续加,否则就减即可

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 21;
int g, b, s, dp[(1<<N) + 5], vis[(1<<N) + 5];
int yu[(1<<N) + 5][10];

struct Page {
    int num;
    int a[10];
} p[N];

int cal(int S, int u) {
    int ans = 0;
    for (int i = 1; i <= g; i++) {
	ans += (yu[S][i] + p[u].a[i]) / s;
    }
    return ans;
}

int dfs(int now) {
    int &tmp = dp[now];
    if (vis[now]) return tmp;
    vis[now] = 1;
    tmp = 0;
    int Min = INF, Max = -INF;
    if (now == (1<<b) - 1) return tmp;
    for (int i = 0; i < b; i++) {
	if (now&(1<<i)) continue;
	int sb = cal(now, i);
	int next = (now|(1<<i));
	if (sb != 0) {
	    Max = max(Max, dfs(next) + sb);
	}
	else {
	    Min = min(Min, dfs(next));
	}
    }
    tmp = max(Max, -Min);
    return tmp;
}

int main() {
    while (~scanf("%d%d%d", &g, &b, &s) && g || b || s) {
	for (int i = 0; i < b; i++) {
	    memset(p[i].a, 0, sizeof(p[i].a));
	    scanf("%d", &p[i].num);
	    int tmp;
	    for (int j = 0; j < p[i].num; j++) {
		scanf("%d", &tmp);
		p[i].a[tmp]++;
	    }
	}
	for (int i = 0; i < (1<<b); i++) {
	    vis[i] = 0;
	    for (int j = 0; j < b; j++) {
		if (i&(1<<j)) continue;
		for (int k = 1; k <= g; k++) {
		    yu[i|(1<<j)][k] = (yu[i][k] + p[j].a[k]) % s;
		}
	    }
	}
	printf("%d\n", dfs(0));
    }
    return 0;
}

HDU 4778 Gems Fight!(dp)

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

HDU 4778 Gems Fight!(dp)的相关文章

hdu 4778 Gems Fight! 状压dp

转自wdd :http://blog.csdn.net/u010535824/article/details/38540835 题目链接:hdu 4778 状压DP 用DP[i]表示从i状态选到结束得到的最大值 代码也来自wdd 1 /****************************************************** 2 * File Name: b.cpp 3 * Author: kojimai 4 * Creater Time:2014年08月13日 星期三 11时

(状压dp)HDU 4778 Gems Fight!

Gems Fight! Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)Total Submission(s): 2395    Accepted Submission(s): 1087 Problem Description Alice and Bob are playing "Gems Fight!": There are Gems of G differe

hdu 4778 Gems Fight!(状态压缩+博弈+记忆化)

Gems Fight! Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others) Total Submission(s): 1383    Accepted Submission(s): 587 Problem Description Alice and Bob are playing "Gems Fight!": There are Gems of G differe

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

[博弈dp] hdu 4778 Gems Fight

给出g种颜色的宝石,然后有B个背包,S代表到时候每种颜色的宝石凑齐S个能变成一个魔法石 然后B行数输入,每个包里有哪些宝石 然后A,B轮流拿包,每个包只能拿一次,拿出包把宝石放地上. 如果能变成魔法石则拿走魔法石,下一次还这个人拿包,没变成则换人. 魔法石的个数就是获得分数,问两人最优的时候分差是多少. 思路: 只有21个包,状压dp. 然后发现不管顺序如何 最后构成的魔法石的个数是一定的. 然后在不同的二进制状态下,所剩在地面上的宝石是一定的. 那么就可以dp[i] 代表i这个状态下 先手取所

hdu 4778 Gems Fight!

第一次写状压dp-- 题意:http://blog.csdn.net/dyx404514/article/details/15506601 状压dp+博弈吧-- #include<iostream> #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<q

hdu 4778 状压dp

题意: 有 G 种颜色的宝石,放在 B 个袋子里(每种颜色可以放多个). 两人轮流选袋子(每个袋子只能被选 1 次),每次将选出来的袋子中的宝石放到 cooker 中,cooker 可能会起反应. 反应条件是 cooker 中出现 S 个一样颜色的宝石,而且一旦起反应,每 S 个一样颜色的宝石就会获得 1 个魔法石(同时反应). 作为奖励,每次反应结束后当前玩家可以再选一个袋子继续游戏. 游戏目标是自己获得的魔法石尽量多,双方都采取最优策略的情况下,问最终两个玩家的魔法石之差最大值. 思路: 数

hdu 4778 Rabbit Kingdom(状态压缩)

题目链接:hdu 4778 Rabbit Kingdom 题目大意:Alice和Bob玩游戏,有一个炉子,可以将S个相同颜色的宝石换成一个魔法石,现在有B个包,每个包里有若干个宝石,给出宝石的颜色.现在由Alice开始,两人轮流选取一个包的宝石放入炉中,每当获得一个魔法石时,可以额外获得一次机会再选一个包放入.两人均按照自己的最优策略,问说最后Alice的魔法石-Bob的魔法石是多少. 解题思路:状态压缩,221,对于每次移动到下一个状态,如果获得的魔法石g非零,则说明下一个状态还是自己在取,则

HDU 4960 (水dp)

Another OCD Patient Problem Description Xiaoji is an OCD (obsessive-compulsive disorder) patient. This morning, his children played with plasticene. They broke the plasticene into N pieces, and put them in a line. Each piece has a volume Vi. Since Xi