[博弈][DP]DLUTOJ1328: Bricks Game

鏈接:http://acm.dlut.edu.cn/problem.php?id=1328

 

直接貼代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;

const int maxn = 1e5 + 50;
ll arr[maxn],sum[maxn];
ll dp[maxn][3];

ll Max(ll a, ll b, ll c){
    return max(max(a,b), c);
}

int main()
{
    freopen("input.txt","r",stdin);
    int T,i,n;
    cin>>T;
    while(T--){
        memset(sum,0,sizeof(sum));
        memset(dp,0,sizeof(dp));
        cin>>n;
        for(i=0;i<n;i++){
            cin>>arr[i];
        }
        sum[n] = 0;
        for(i=n-1;i>=0;i--){
            sum[i] = sum[i+1] + arr[i];
        }
        if(n<=3){
            cout<<sum[0]<<endl;
            continue;
        }
        /*
        dp[n-1][1] = arr[n-1];
        dp[n-2][1] = arr[n-2];
        dp[n-2][2] = arr[n-2] + arr[n-1];
        dp[n-3][1] = arr[n-3];
        dp[n-3][2] = arr[n-3] + arr[n-2];
        dp[n-3][3] = arr[n-3] + arr[n-2] + arr[n-1];
        */

        for(i=n-1;i>=0;i--){
            dp[i][1] =  sum[i+1] - Max(dp[i+1][1],dp[i+1][2],dp[i+1][3]) + arr[i];
            dp[i][2] =  sum[i+2] - Max(dp[i+2][1],dp[i+2][2],dp[i+2][3]) + arr[i] + arr[i+1];
            dp[i][3] =  sum[i+3] - Max(dp[i+3][1],dp[i+3][2],dp[i+3][3]) + arr[i] + arr[i+1] + arr[i+2];
        }
        ll ans = Max(dp[0][1],dp[0][2],dp[0][3]);
        cout<<ans<<endl;
    }
    return 0;
}


 

原理:

dp[i][j]表示取從i位置起(包括i)的j個方塊,所能達到的總共最大值。
遞推公式,比如
dp[i][2] =  
sum[i+2]                                                                        //[i+2]~[n-1]塊的數字和
 - Max(dp[i+2][1],dp[i+2][2],dp[i+2][3])                       //玩家B在[i+2]塊起選一個最優策略
 + arr[i] + arr[i+1];                                                          // 這是i起兩個塊

 

PS: 雖然是自己想出來的,但是並不太清楚dp這個數組爲啥既能代表A的最優策略,也能代表B的最優策略。。他倆一個先手一個後手啊。。

 

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