codeforcesB - A Lot of Games 博弈+dp

题意:给你n个字符串,给你一个序列,两个人轮流取一个字符使得现有的字符串是n个字符串里面的前缀,最后谁不能取谁就输掉这局,但是他们要玩K局,谁在K局赢了就等于赢了一整场比赛。

解题思路:字典树找是否有 必输 或者 必赢 的策略,如果同时有必赢或者必输的策略,那必定是first赢,如果只有必赢,那只需要讨论K奇偶,如果只有必输,那一定是second

解题代码:

  1 // File Name: 1.cpp
  2 // Author: darkdream
  3 // Created Time: 2014年07月12日 星期六 23时30分16秒
  4
  5 #include<vector>
  6 #include<list>
  7 #include<map>
  8 #include<set>
  9 #include<deque>
 10 #include<stack>
 11 #include<bitset>
 12 #include<algorithm>
 13 #include<functional>
 14 #include<numeric>
 15 #include<utility>
 16 #include<sstream>
 17 #include<iostream>
 18 #include<iomanip>
 19 #include<cstdio>
 20 #include<cmath>
 21 #include<cstdlib>
 22 #include<cstring>
 23 #include<ctime>
 24 #include<climits>
 25 #include<queue>
 26
 27 using namespace std;
 28
 29 struct node{
 30     int num;
 31     int ok;
 32     int ok1;
 33     struct node *next[30];
 34 };
 35 struct node* newnode(){
 36    struct node * p = (node *)malloc(sizeof(node));
 37    for(int i =0 ;i < 30;i ++)
 38        p->next[i] = NULL;
 39    p->ok = 0;
 40    p->num = 0  ;
 41    return p ;
 42 }
 43 char str[100004];
 44 int len ;
 45 void build(struct node * p, int i )
 46 {
 47
 48    int k = str[i] -‘a‘;
 49    if(i == len )
 50        return ;
 51   if(p->next[k] == NULL)
 52    {
 53      struct node * t  = newnode();
 54      t->num ++;
 55      p->next[k] =  t;
 56      build(p->next[k],i+1);
 57    }
 58   else {
 59       p->next[k]->num += 1;
 60       build(p->next[k],i+1);
 61    }
 62   int tok = 0 ;
 63   int nok = 0 ;
 64   int t1ok = 0 ;
 65   for(int i= 0;i < 30 ;i ++)
 66   {
 67      if(p->next[i] != NULL)
 68      {
 69         nok = 1;
 70         if(p->next[i]->ok == 0 )
 71             tok = 1;
 72         if(p->next[i]->ok1 == 1)
 73             t1ok = 1;
 74      }
 75   }
 76   if(!nok || tok)
 77       p->ok = 1;
 78   else p->ok = 0;
 79   if(nok)
 80   {
 81     if(t1ok)
 82      p->ok1 = 0;
 83     else p->ok1 =1;
 84   }else{
 85      p->ok1 = 0;
 86   }
 87 }
 88 int ans;
 89 void find(struct node * p, int i )
 90 {
 91    int k = str[i] -‘a‘;
 92    if(i == len )
 93     {
 94       ans = p->num ;
 95       return ;
 96     }
 97    if(p->next[k] == NULL)
 98    {
 99       return ;
100    }else find(p->next[k],i+1);
101 }
102 int main(){
103     int n , k;
104
105     struct node * head = newnode();
106     scanf("%d %d",&n,&k);
107     while(n --){
108          scanf("%s",str);
109          len = strlen(str);
110          build(head,0);
111     }
112    // printf("%d %d\n",head->ok,head->ok1);
113     if(head->ok)
114     {
115       if(!head->ok1)
116          printf("First\n");
117       else{
118         if(k % 2 == 1)
119             printf("First\n");
120         else printf("Second\n");
121       }
122     }else{
123        printf("Second\n");
124     }
125 return 0;
126 }

codeforcesB - A Lot of Games 博弈+dp

时间: 2024-08-30 04:39:28

codeforcesB - A Lot of Games 博弈+dp的相关文章

UVA 1558 - Number Game(博弈dp)

UVA 1558 - Number Game 题目链接 题意:20之内的数字,每次可以选一个数字,然后它的倍数,还有其他已选数的倍数组合的数都不能再选,谁先不能选数谁就输了,问赢的方法 思路:利用dp记忆化去求解,要输出方案就枚举第一步即可,状态转移过程中,选中一个数字,相应的变化写成一个函数,然后就是普通的博弈问题了,必胜态之后必有必败态,必败态之后全是必胜态 代码: #include <stdio.h> #include <string.h> const int N = 105

UVA 1557 - Calendar Game(博弈dp)

UVA 1557 - Calendar Game 题目链接 题意:给定一个日期,两个人轮流走,每次可以走一月或者一天,问最后谁能走到2001.11.4这个日子 思路:记忆化搜索,对于每个日期,如果下两个状态有一个非必胜态,那么这个状态是必胜态,如果后继状态都是必胜态,那么该状态为必败态 代码: #include <stdio.h> #include <string.h> const int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31,

UVA 1559 - Nim(博弈dp)

UVA 1559 - Nim 题目链接 题意:一开始有s个石子,2n个人轮流取石子,每个人有个最大能取数目,2n个人奇数一队,偶数一队,取到最后一个石子的队输,问谁赢 思路:记忆化搜索,每个人取的时候对应的后继状态如果有一个必败态,则该状态为必胜态,如果都是必胜态,则该状态为必败态 代码: #include <stdio.h> #include <string.h> int n, s, m[25], dp[25][10005]; int dfs(int now, int state

UVa 10891 (博弈+DP) Game of Sum

最开始的时候思路就想错了,就不说错误的思路了. 因为这n个数的总和是一定的,所以在取数的时候不是让自己尽可能拿的最多,而是让对方尽量取得最少. 记忆化搜索: d(i, j)表示原序列中第i个元素到第j个元素构成的子序列,先手取数能够得到的最大值. sum(i, j) 表示从第i个元素到第j个元素的和 因为要让对手获得最小的分数,所以状态转移方程为: d(i, j) = sum(i, j) - min{d(枚举所有可能剩给对手的序列), 0(0代表全部取完)} s数组保存a中前i个元素的和,这样s

codeforces 455B(博弈+dp)

题目链接: codeforces 455B 题目大意: 给出n个字符串,进行k次游戏,每次游戏输家下次作为先手,游戏规则为每次放一个字母,导致当前构造的字符串是给定的任意一个字符串的前缀,不能操作时为输,赢得第k次比赛的人会取得最终的胜利,问两人都采取最优策略的情况下,谁会赢得比赛. 题目分析: 首先针对这种字符串的问题我们很容易会想到利用字典树来解决,方便多模式匹配. 然后我们就能想到,这其实就是一个在树上的博弈,那么我们就可以通过dp知道先手是否有必胜策略和必败策略. 这个树上的博弈很基础,

hdu-4597 (博弈DP)

该题是用dp推导博弈题的经典例子 , 仔细想想就会发现,这其实就是一个区间处理的问题 ,一般区间问题还是比较简单的一类题目 . 由于两个孩子都很聪明,所以他们一定都尽可能的选择最优方案,所以每个人当前的最优解都依赖于下一个人的最优解 .    那么怎么处理细节呢 ? 还是老调重弹,先想状态如何表示,再想状态如何转移 . 很显然,要想完整的描述状态,我们必须开四维数组,记录两堆牌当前的状态 .  那么状态不难表示成  d[al][ar][bl][br] , 表示两堆牌当前的首尾情况下,所能获得的最

acm山东省赛 Games(dp取数)

Games Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Problem Description Alice and Bob are playing a stone game. There are nn piles of stones. In each turn, a player can remove some stones from a pile (the number must be positive and no

uvalive6913 I Want That Cake(博弈dp)

引自:http://www.cnblogs.com/qscqesze/p/5734143.html 题意: 有两支队,每只队都有n个人,一共有m个蛋糕,每个人至少吃一个,最多吃k个. 都采取最优策略,谁吃到最后一个蛋糕,那么那只队就胜利. 按照给定的顺序去吃蛋糕,问你最后谁胜利. 思路: 先缩点,把相同的点都缩成一个点. 那么就变成了ABABABA这样交替的形式了,然后跑DP就好了. dp[i][j]代表第i层代表的队伍蛋糕还剩j个时的状态 0为必败态,1为必胜态 首先,能把蛋糕吃完的状态为必胜

[博弈dp] hdu 4778 Gems Fight

给出g种颜色的宝石,然后有B个背包,S代表到时候每种颜色的宝石凑齐S个能变成一个魔法石 然后B行数输入,每个包里有哪些宝石 然后A,B轮流拿包,每个包只能拿一次,拿出包把宝石放地上. 如果能变成魔法石则拿走魔法石,下一次还这个人拿包,没变成则换人. 魔法石的个数就是获得分数,问两人最优的时候分差是多少. 思路: 只有21个包,状压dp. 然后发现不管顺序如何 最后构成的魔法石的个数是一定的. 然后在不同的二进制状态下,所剩在地面上的宝石是一定的. 那么就可以dp[i] 代表i这个状态下 先手取所