写在前面的话

知识基础:一些基础的博弈论的方法,动态规划的一些知识

前言:博弈论就是一些关于策略或者游戏之间的最优解,动态规划就是对于一些状态之间转移的一些递推式(or 递归),dp分为很多很多种,比如状压dp我感觉其实就是一种暴力,数位dp也可以用记忆化搜索的形式解决。可见动态规划其实是解决一些不能快速解决,不能以O(1)方法解决的问题,而博弈之中,经常会出现一些O(1)方法解决的策略,或者O(n),可见博弈dp它有其不确定性(或者说有不能直接解决的方案)所以需要在博弈的基础上加上dp。举一个很简单的例子,但这个例子没有什么实质性的意义,知识为了帮助理解博弈dp,比如有一个01串,两个人轮流取其中的数字,要求下一次取的那个的下标必须比前一个取的下标要大,比如第一个人取第一个,第二个人只能取(2-n)个。很简单吧,然后问你两个人最多可以加起来取多少个1。你肯定会说这要dp啥,这要博弈啥,我就举个例子嘛。博弈在这里面就是每个人都取前一次取的那个的后面的那个是不是就是最优的啦,dp就当作枚举第一个人拿去的第一个数的下标是几,然后可以拿到多少个1,比如dp[m]就是第一个人取第m个可以拿到的最多的1的个数。

现在就来看poj-1678这道题

题意:2个人轮流拿数组里面的一个数,且要比另外一个人上一次拿的数大[a,b],第一次拿要拿[a,b]范围的数,求第一个人拿的总和比第二个人的总和最多大多少

思考:很明显,他们拿的肯定是一个比一个大(题目里说了0<a<b),所以先排个序那就是肯定是按照从左往右取的对吧。

看个样例:

6 1 2

1 3 -2 5 -3 6

把它排序之后就是:

6 1 2

-3 -2 1 3 5 6

很明显第一个人只能取1,然后第二个人取3,第一个人再取5,第二个人再取6,那么差值就是1+5-3-6 = -3

看了这个样例你肯定会感觉看了和没看一样,因为这里取的情况被锁死了,那我们来看看下一个我瞎造的样例

8 1 10

1 2 3 4 5 6 7 8

假设第一个人先后取1 3 5 7,第二个人先后取2 4 6 8,这个是符合题意的,然而差值是-4,甚至是player2赢了

假设第一个人先后取3 5 7,第二个人先后取4 6 8,这个也是符合题意的,然而差值是-3,还是player2赢了

假设第一个人先后取4 6 8,第二个人先后取5 7,这个也是符合题意的,差值为6,player1赢了

最优解就是第一个人直接就是取8,那么第二个人取不了了,差值为8,player1赢了,甚至没有给player2一个后手,太狠了

所以发现问题了吗,player1第一次取的那个数字是什么是影响结果的,同时,假如第一个人选1,第二个人直接选8也是可行,可见第二个人的选法也是影响结果的,所以这就是一个dp,或者可以说是一个记忆化的搜索。

看看代码就会知道,soga

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<cstdlib>
#include <vector>
#include <set>
#include<queue> using namespace std; #define ll long long
#define llu unsigned long long
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
const int maxn = 1e4+;
int num[maxn];
int n,a,b;
int dp[maxn]; void init()
{
for(int i=;i<n;i++)
dp[i] = -INF;
}
int DP(int m)
{
if(dp[m] != -INF) //dp[m]表示如果先手取了第m个数,可以达到的最大的分差
return dp[m]; //如果第m个数已经取了,直接就return,这个不加可能会t
int ans = INF;
for(int i=m+;i<n;i++)
if(num[i]-num[m] >= a && num[i]-num[m] <= b)
ans = min(ans,num[m] - DP(i)); //dp就是枚举最后一个状态,如果最后一个状态已经涵盖了,那么之前的所有状态都涵盖了
if(ans == INF)//取不了了
return dp[m] = num[m];
return dp[m] = ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&a,&b);
init();
for(int i=;i<n;i++)
scanf("%d",&num[i]);
sort(num,num+n);
int ans = -INF;
for(int i=;i<n;i++) //枚举第一个人拿的每一个数
if(num[i] >= a && num[i] <= b)
ans = max(ans,DP(i));
printf("%d\n",ans == -INF ? : ans);
}
}

博弈dp 以I Love this Game! POJ - 1678 为例的更多相关文章

  1. 博弈dp入门 POJ - 1678 HDU - 4597

    本来博弈还没怎么搞懂,又和dp搞上了,哇,这真是冰火两重天,爽哉妙哉. 我自己的理解就是,博弈dp有点像对抗搜索的意思,但并不是对抗搜索,因为它是像博弈一样,大多数以当前的操作者来dp,光想是想不通的 ...

  2. HDU 5623 KK's Number (博弈DP)

    KK's Number 题目链接: http://acm.hust.edu.cn/vjudge/contest/121332#problem/K Description Our lovely KK h ...

  3. POJ 1678 I Love this Game!#dp博弈

    http://poj.org/problem?id=1678 #include<iostream> #include<cstdio> #include<cstring&g ...

  4. poj 2068 Nim(博弈dp)

    Nim Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 1403   Accepted: 791 Description Le ...

  5. tyvj P1075 - 硬币游戏 博弈DP

    P1075 - 硬币游戏 From price    Normal (OI)总时限:10s    内存限制:128MB    代码长度限制:64KB 背景 Background 农民John的牛喜欢玩 ...

  6. UVA 1558 - Number Game(博弈dp)

    UVA 1558 - Number Game 题目链接 题意:20之内的数字,每次能够选一个数字,然后它的倍数,还有其它已选数的倍数组合的数都不能再选,谁先不能选数谁就输了,问赢的方法 思路:利用dp ...

  7. 计蒜客 取数游戏 博弈+dp

    题目链接 取数游戏 思路:dp(x, y)表示先手在区间[x, y]能取得的最大分数.当先手取完,就轮到后手去,后手一定会选择当前能令他得到最大分数的策略,其实当先手在[x, y]区间两端取走一个数, ...

  8. Beans Game(博弈 | | DP)zoj 3057

    Beans Game Time Limit: 5 Seconds Memory Limit: 32768 KB There are three piles of beans. TT and DD pi ...

  9. 【HDOJ5951】Winning an Auction(博弈DP)

    题意:A和B两个人做一个拍卖游戏.每一轮两人分别给出一个价格,出价高者获得该轮的物品,出价相同则奇数轮A优先,偶数轮B优先. 两个人的目标都是最大化自己的商品数量,给定轮数n与两人分别的总资金a,b, ...

随机推荐

  1. March 10 2017 Week 10 Friday

    If you love life, life will love you back. 爱生活,生活也会爱你. Love life, and it will love you back. All thi ...

  2. 遍历目录树 - Unicode 模式

    =info     遍历目录树 支持 Unicode     Code by 523066680@163.com     2017-03         V0.5 使用Win32API判断目录硬链接 ...

  3. Opportunity的chance of success的赋值逻辑

    该字段的值和另外两个字段Sales Stage和Status都相关. 从下列function module CRM_OPPORT_H_PROB_SET_EC可看出,当status不为代码中的这些硬编码 ...

  4. CF235C 【Cyclical Quest】

    厚颜无耻的发一篇可能是全网最劣解法 我们发现要求给定的串所有不同的循环同构出现的次数,可以直接暴力啊 因为一个长度为\(n\)的串,不同的循环同构次数显然是不会超过\(n\)的,所以我们可以直接对每一 ...

  5. 最短路算法 —— Dijkstra算法

    用途: 解决单源最短路径问题(已固定一个起点,求它到其他所有点的最短路问题) 算法核心(广搜): (1)确定的与起点相邻的点的最短距离,再根据已确定最短距离的点更新其他与之相邻的点的最短距离. (2) ...

  6. where are you going ? 反序为:going you are where

    一个反序小算法,就是首尾替换,生成新的反序后的数组

  7. ssh公钥

    想要将本地电脑的文件传到github上,必须要通过建立本地电脑与github帐号的ssh公钥才行. 方式: 用命令ssh-keygen产生ssh公钥(之后一直按回车就好),然后cd到~/.ssh目录, ...

  8. Window下搭建foundation apps环境

    Window下搭建foundation apps环境 框架:AngularJS.Foundation, 构建工具:Gulp, 开发环境:node.js. 操作系统:windows (一)环境准备 1 ...

  9. 【洛谷P3959】[NOIP2017] 宝藏

    宝藏 题目链接 首先,打了一个prim,得了45分 #include<iostream> #include<cstring> #include<cstdio> #i ...

  10. 1..net转java背景介绍

    注册博客2年了.从注册就开始接触.net.以前也有想过转java.只是没想过会这么快. .net语法这么优美好用.可惜了生态环境. .net还没有学成大神.就要离开了. 公司有个项目要用java.在加 ...