题目链接
思路:
细节的处理尤为重要,后面会提点一下。
这道题,我的想法是从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了好几发了,所以得写下来,避免同样犯错的读者。
-
如果dp[i-1]是Alice死,那么到了i时刻,就意味着有一次交换,而交换是需要1s时间的,故生死转换。
-
遍历得从1~T且一定是1开始,因为0时刻反正是直接爆的。
-
访问前面的节点生死关系时,一定要注意时间得>=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;
}