排成一條線的紙牌博弈問題

/***************************************************************************
 *description:排成一條線的紙牌博弈問題
 *            給定一個整型數組arr,代表數值不同的紙牌排成一條線
 *            玩家A和玩家B依次拿走每張紙牌,規定A先拿。
 *            每個玩家每次只能拿走最左或最右的紙牌。
 *            返回最後獲勝者的分數。
 *            例:arr=[1,2,100,4]
 *                玩家A拿走1,然後B拿走2或4,A再拿100,返回101

 **************************************************************************/

#include<iostream>
#include<vector>
using namespace std;

//方法1:暴力遞歸。時間複雜度O(2^N),空間複雜度O(N)
//定義函數f[i][j]表示arr[i...j]被絕頂聰明的人先拿得到的分數。
//              i==j時,就一張牌,直接返回arr[i];否則該人只能拿arr[i]或arr[j]:
//              拿arr[i],剩下的arr[i+1...j]他變成後拿的人;拿arr[j],剩下的arr[i...j-1]他變成後拿的人;
//              所以函數返回max(arr[i]+s[i+1][j], arr[j]+s[i][j-1])
//定義函數s[i][j]表示arr[i...j]被絕頂聰明的人後拿得到的分數。
//              i==j時,先拿的拿走,後拿的沒有,返回0;否則
//              先拿的人可能拿走arr[i]或arr[j].由於先拿的也是絕頂聰明
//              所以函數返回min(f[i+1][j],f[i][j-1])
int f(vector<int> arr, int left, int right);
int s(vector<int> arr, int left, int right)
{
    if (left == right)
        return 0;
    return min(f(arr,left+1,right),f(arr,left,right-1));
}
int f(vector<int> arr, int left, int right)
{
    if (left == right)
        return arr[left];
    return max(arr[left]+s(arr,left+1,right), arr[right]+s(arr,left,right-1));
}

int winerScore_1(vector<int> arr)
{
    if (arr.size() == 0)
        return 0;

    return max(f(arr, 0, arr.size()-1), s(arr, 0, arr.size()-1));
}
//方法2:動態規劃。時間複雜度O(N^2),空間複雜度O(N^2)

int winerScore_2(vector<int> arr)
{
    if (arr.size() == 0)
        return 0;

    int N = arr.size();

    vector<vector<int>> s(N,N);
    vector<vector<int>> f(N,N);
    f[0][0] = arr[0];
    s[0][0] = 0;
    for (int i = N-1; i >= 0; i--)
    {
        f[i][i] = arr[i];
        s[i][i] = 0;
        for (int j = i+1; j < N; j++)
        {
            f[i][j] = max(arr[i]+s[i+1][j], arr[j]+s[i][j-1]);
            s[i][j] = min(f[i+1][j], f[i][j-1]);
        }
    }
    return max(s[0][N-1], f[0][N-1]);
}
int main()
{
    vector<int> arr;
    arr.push_back(1);
    arr.push_back(2);
    arr.push_back(100);
    arr.push_back(4);
    cout << winerScore_2(arr);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章