博弈论的一些理解

博弈论的一些理解

一、起因

  之前在某个可怕的比赛中看到了博弈论的签到题,但是由于三个人没有一个学过博弈论以至于强行放弃的事故发生。我决定立刻,马上开坑博弈论专题。

二、分类以及相关题目

  1. 动态博弈
      POJ1678
      UVA3668

  2. 巴士博弈

三、题解

  1、POJ1678

   首先分析题目,可以发现,a,b的具体大小大于0,则这意味着每次选取的时候后一个数必然大与前一个数字。因此具有单调性,可以先将数组排序。(按照这个道理其实可以去除掉所有小于a的数字)

   其次,首先假设dp[i]代表当先手面临arr[i]时的最优选择,则,应当认为,每次状态转移的目的实际上是在替后手做决策——在当前状态选取最小收益的点作为后续选择。

   最后考虑特殊点——游戏结束点,dp[i]应当为arr[i]本身。

#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
using namespace std;

#define ll long long 
const ll MAXN=100233;
const ll INF = (ll)1<<40;
ll arr[MAXN];
ll dp[MAXN];

ll n,a,b;

void init()
{
    cin>>n>>a>>b;
    for(int i=0;i<n;++i)    cin>>arr[i];
    sort(arr,arr+n);
    for(int i= n-1;i>=0;--i)
    {
        dp[i] = INF;
        for(int j=i+1;j<n;++j)
        {
            if(arr[j]<arr[i]+a)continue;
            if(arr[j]>arr[i]+b)break;
            dp[i] = min(arr[i] - dp[j],dp[i]);
        }
        if(dp[i] == INF)dp[i] = arr[i];
    }
    ll ans = -INF;
    for(int i=0;i<n;++i)
    {
        if(arr[i] < a)continue;
        if(arr[i] > b)break;
        ans = max(dp[i],ans);
    }
    if(ans == -INF)ans = 0;
    cout<<ans<<"\n";
    
    
}

int main()
{
    
    int t;
    cin>>t;
    while(t--)
        init();
    
    return 0;
    
}
POJ1678

猜你喜欢

转载自www.cnblogs.com/rikka/p/9074864.html