1. 程式人生 > >自殺遊戲【牛客小白月賽7 B】【DP動態規劃】【詳解、對於WA細節上的分析】

自殺遊戲【牛客小白月賽7 B】【DP動態規劃】【詳解、對於WA細節上的分析】

題目連結

  思路

細節的處理尤為重要,後面會提點一下。

這道題,我的想法是從0這個必死局開始往後找最優解下Alice或者Bob的生死,初始化dp[]是全Bob活,也就是Alice死,dp【i】是指以最優解往下走,到達i時刻死的人到底會是誰,然後從1號節點開始遍歷,由於a、b很小,所以這道題我的O(t*(b-a))的時間複雜度還是可行的。

我遍歷到點i,然後找它前面的時間線【i-b-1,i-a-1】(後面簡稱之為區間K),這麼尋覓也是有原因的,若是區間K存在這樣的點是Bob活,而在此情況,一定是Alice要找生存的機會,所以得反轉,那麼dp[i]時刻就是true(Alice找到生的機會),反之就無須,畢竟初始化就是全都是Bob贏的。

  細節

我在細節處WA了好幾發了,所以得寫下來,避免同樣犯錯的讀者。

  1. 如果dp[i-1]是Alice死,那麼到了i時刻,就意味著有一次交換,而交換是需要1s時間的,故生死轉換。

  2. 遍歷得從1~T且一定是1開始,因為0時刻反正是直接爆的。

  3. 訪問前面的節點生死關係時,一定要注意時間得>=0,不然就不存在這樣的時間。

完整程式碼

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef long long ll;
const int maxN=1e5+5;
int T, a, b;
bool dp[maxN];      //如果i時刻為true就是Alice活,否則Bob活
int main()
{
    while(scanf("%d%d%d",&T, &a, &b)!=EOF)      //一共有T時間緩衝爆炸
    {
        memset(dp, false, sizeof(dp));
        for(int i=1; i<=T; i++)       //i指的是到目前狀態時候,誰會死,從1開始,因為0是必死局
        {
            if(!dp[i-1]) dp[i]=true;
            for(int j=i-b-1; j<=i-a-1; j++)
            {
                if(j>=0 && !dp[j])      //若是j時刻是Bob死,那麼這次尋取最優解就是Alice活
                {
                    dp[i]=true;
                    break;
                }
            }
        }
        printf(dp[T]?"Alice\n":"Bob\n");
    }
    return 0;
}