hdu 4778 Gems Fight! 博弈+状态dp+搜索
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4102743.html
题目链接:hdu 4778 Gems Fight! 博弈+状态dp+搜索
不难发现,无论Alice和Bob以何种方式投掷包裹,他们得到的Magic Stones个数的和$Sum$是一定的,因此只需要计算Alice可以获得的最大的Magic Stones的个数MAXA,则Bob获得的个数为Sum-MAXA,而两者的最大的差为MAXA-(sum-MAXA)为答案。那么如何计算MAXA呢?我们定义状态state为目前包裹的使用情况,如果包裹i被使用则state的二进制的第i位为0,否则为1。我们可以发现如下性质:
Alice和Bob的目的是相同的,即使得获得的Magic Stones的个数最大。唯一的区别就是Alice先手,而Bob后手。如果Alice这一轮没有获得Magic Stone,那么权利转移给Bob,Bob的策略则和Alice在相同的状态state下先手的策略是相同的。从而可以定义dp[state],表示在先手的情况下(无论是Alice还是Bob)能够获得的最大的Magic Stones数目。从而可以使用深度优先的记忆化搜索。对于一个状态$state$,如果第i个包裹还没有被使用,则计算先手把这个包裹投入cooker中所能获得的magic stone的个数gen,如果gen>0则说明可以继续保持先手,获得的Magic Stones得个数等于此次获得和个数加上在下一个状态下先手投掷所能获得的最大的个数。否则的话先手转化为后手,所获得的Magic Stones的个数只能为此状态下所能产生所有的的Magic stones的个数减去先手在下一状态下所能获得的最大的个数。我们用gen表示此次向cooker中投掷i包裹能够获得的magic的个数,cc表示cooker的状态,即各个颜色石头的个数。left表示目前状态下所能产生的所有的Magic stones的个数。
代码如下:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
using namespace std;
const int MAXB = ;
const int MAXC = ;
const int MIN = -;
int g, b, s;
int bag[MAXB][MAXC];
int color[MAXC];
int dp[<<MAXB];
int dfs(int state,int left, int *c)
{
if( state == || left == ) return ;
if( dp[state] != MIN ) return dp[state];
int maxres = MIN;
int maxtmp = ;
for( int i = ; i < b ; i++ )
{
int cc[MAXC];
memset(cc, , sizeof(cc));
int gen = ;
if( state>>i & )
{
for( int j = ; j < g ; j++ )
{
cc[j] = c[j] + bag[i][j];
gen += cc[j]/s;
cc[j] %= s;
}
if( gen > )
{
maxtmp = gen + dfs(state^(<<i), left-gen, cc);
}
else
{
maxtmp = left - dfs(state^(<<i), left, cc);
}
}
maxres = max(maxres, maxtmp);
}
dp[state] = maxres;
return maxres;
}
int main(int argc, char *argv[])
{
while( )
{
scanf("%d%d%d", &g, &b, &s);
if( g == && b == && s == ) return ;
memset(bag, , sizeof(bag));
memset(color, , sizeof(color));
int sum = ;
for( int i = ; i < b ; i++ )
{
int tmpn;
scanf("%d", &tmpn);
while( tmpn -- )
{
int c;
scanf("%d", &c);
bag[i][c-]++;
color[c-]++;
}
}
for( int i = ; i < g ; i++ )
{
sum+=color[i]/s;
}
for( int i = ; i < (<<MAXB) ; i++ )
{
dp[i] = MIN;
}
int cc[MAXC];
memset(cc, , sizeof(cc));
int res = dfs((<<MAXB)-, sum, cc);
printf("%d\n", res-(sum-res));
}
}
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状态选到结束得 ...
- Hdu 4778 Gems Fight! (状态压缩 + DP)
题目链接: Hdu 4778 Gems Fight! 题目描述: 就是有G种颜色,B个背包,每个背包有n个宝石,颜色分别为c1,c2............两个人轮流取背包放到公共容器里面,容器里面有 ...
- HDU 4778 Gems Fight! (2013杭州赛区1009题,状态压缩,博弈)
Gems Fight! Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/Others)T ...
- hdu 4778 Gems Fight! 状态压缩DP
Gems Fight! Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/Others)T ...
- HDU 4778 Gems Fight!(DP)
题目链接 当我放弃的时候过了.sb啊,卡常数!!! 换了好几个姿势,本来没写预处理,预处理+俩剪枝,尼玛就过了.. #include <stdio.h> #include <stri ...
- hdu 4778 Gems Fight!
第一次写状压dp-- 题意:http://blog.csdn.net/dyx404514/article/details/15506601 状压dp+博弈吧-- #include<iostrea ...
- hdu 5135(2014广州—状态dp)
t题意:给你n条边,构造任意个三角形,一个三角形恰好只用3条边,每条边只能一次,求面积最大值 思路: 最开始想的是先排序从大到小取,但感觉并不怎么靠谱. 最多12条边,所以可以求出所有可能的三角形面积 ...
- hdu 5025 Saving Tang Monk 状态压缩dp+广搜
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4092939.html 题目链接:hdu 5025 Saving Tang Monk 状态压缩 ...
- HDU 4778 状压DP
一看就是状压,由于是类似博弈的游戏.游戏里的两人都是绝对聪明,那么先手的选择是能够确定最终局面的. 实际上是枚举最终局面情况,0代表是被Bob拿走的,1为Alice拿走的,当时Alice拿走且满足变换 ...
随机推荐
- 百度之星资格赛,hdu 4825 XOR SUM
显然是要建一棵0.1树 事实上非常easy就是二叉树,仅仅只是为了操作简便,即程序的速度,所以就採用静态树,即不动态分配内存,使用较大的全局数组.0是根节点 #include<cstdio> ...
- iOS蓝牙中的进制转换
Bluetooth4.0.jpg 最近在忙一个蓝牙项目,在处理蓝牙数据的时候,经常遇到进制之间的转换,蓝牙处理的是16进制(NSData),而我们习惯的计数方式是10进制,为了节省空间,蓝牙也会把16 ...
- BAPI_ACC_DOCUMENT_POST Enter rate / GBP rate type M for Error SG105
Folks, I was wondering if I could get a bit of help here as I've been racking my brains on it for ag ...
- 应聘.net开发工程师常见的面试题(一)(转载)
1. 简述 private. protected. public. internal 修饰符的访问权限. 答 . private : 私有成员, 在类的内部才可以访问. protected : 保护成 ...
- Linux下用dump实现备份和还原 ux下用dump实现备份和还原
对于系统而言,我们可以有很多种办法去备份(还原)系统或文件,之所以要去做备份,就是为了在系统或文件遭到损害时,能及时恢复,把损失减小到最小.当然,对于企业服务器而言,备份的重要性是举足轻重.咱们今天就 ...
- endif、endforeach
<?php if ($a == 5): ?> <div>等于5</div><?php elseif ($a == 6): ?> <div> ...
- JS 笔记
如何定义一个函数呢?基本语法如下: function 函数名() { 函数代码; } 说明: 1. function定义函数的关键字. 2. "函数名"你为函数取的名字. ...
- swift switch语句
switch选择 1)case多条件匹配:条件之间用逗号隔开 用三个点表示范围:…,..<:表示不包含上边界 var tand = 1 switch tand{ case 0: ...
- Android_listview_scrollListener
layout.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" x ...
- MyBatis5:MyBatis集成Spring事务管理(上篇)
前言 有些日子没写博客了,主要原因一个是工作,另一个就是健身,因为我们不仅需要努力工作,也需要有健康的身体嘛. 那有看LZ博客的网友朋友们放心,LZ博客还是会继续保持更新,只是最近两三个月LZ写博客相 ...