写在前面的话

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

前言:博弈论就是一些关于策略或者游戏之间的最优解,动态规划就是对于一些状态之间转移的一些递推式(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);
}
}

最新文章

  1. Mysql 迁移最完整可用的教程
  2. [解决]Mercurial HTTP Error 500: Access is denied on&#160;00changelog.i
  3. css中background背景属性概
  4. buildbot入门系列—介绍篇
  5. 转:python webdriver API 之对话框处理
  6. mha的搭建步骤(一主一从架构)
  7. 常见HTTP状态(304,200等)
  8. 每天一个小算法(Shell Sort2)
  9. CentOs Linux 分区建议
  10. Java编程思想读书笔记--第14章类型信息
  11. 关于Hyper-V虚拟机中的vEthernet虚拟网卡不能联网的问题
  12. MQTT学习笔记——Yeelink MQTT维修 采用mqtt.js和paho-mqtt
  13. 多快好省的做个app开发
  14. Linux下的IO监控与分析
  15. ER模型的学习
  16. HDU 5976 数学
  17. CSS架构的优选和解决方案
  18. Windbg分析高内存占用问题
  19. RecyclerViewLoadMoreDemo【封装上拉加载功能的RecyclerView,搭配SwipeRefreshLayout实现下拉刷新】
  20. Elasticsearch从入门到精通之Elasticsearch集群内的原理

热门文章

  1. 实现两个N×N矩阵的乘法,矩阵由一维数组表示
  2. tensorflow 模型不兼容
  3. x64 分页机制——虚拟地址到物理地址寻址
  4. QQ空间那年今日 &amp; 人人过往的今天
  5. IOS 蓝牙(GameKit、Core Bluetooth)
  6. 用ant打包apkbuilder找不到了的解决办法
  7. TSP 遗传算法
  8. Nmap的基础知识
  9. maven项目 servlet jar包冲突
  10. 【luogu P1343 地震逃生】 题解