zoukankan      html  css  js  c++  java
  • Codeforces 455B A Lot of Games:博弈dp【多局游戏】

    题目链接:http://codeforces.com/problemset/problem/455/B

    题意:

      给你n个字符串,然后进行k局游戏。

      每局游戏开始有一个空串,然后双方轮流给这个串的末尾添加字符,并保证新字符串是n个字符串中至少一个串的前缀。

      当一方不能添加字符时,这一方输,游戏结束。

      每场游戏结束后,这场游戏输的人会成为下一句游戏的先手。

      谁赢得了最后一场比赛,谁才会真正赢得比赛。

      问你最终真正赢得比赛的人,是第一局游戏的先手还是后手(分别称为First和Second)。

    题解:

      先考虑单局游戏。

      先对原来的n个串,建立一棵trie树。

      那么原游戏就变成了:

        最初有一个棋子在根节点,双方轮流将棋子向下移一格,不能移动的一方输。

      因为每场游戏都是一模一样的,所以每场游戏先手必胜还是必败也是确定的。

      所以游戏的最终赢家取决于,谁能够拿到最后一场游戏的必胜方。

      所以要求的也就不单单是先手是必胜还是必败了。

      而是要分别求:先手能否必胜,和先手能否必败。

      一遍dfs就能解决。

      然后分情况讨论:

        (1)先手只能必胜,不能必败:

          则奇数局的先手是First,First必胜。

          偶数局的先手是Second,Second必胜。

        (2)先手可以必胜,也可以必败:

          那么First会一直让自己输,一直让自己是先手,直到最后一局再赢。

          所以此时First必胜。

        (3)先手不能必胜,只能必败:

          也就是无论怎样操作,First一直都是先手,所以Second必胜。

        (4)先手不能必胜,也不能必败:

          也就是后手既可以必胜,也可以必败。

          所以后手会一直让自己赢,一直让自己是后手,所以Second必胜。

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #define MAX_N 100005
     5 #define MAX_L 100005
     6 #define MAX_A 30
     7 
     8 using namespace std;
     9 
    10 struct Node
    11 {
    12     int nex[MAX_A];
    13     Node()
    14     {
    15         memset(nex,0,sizeof(nex));
    16     }
    17 };
    18 
    19 int n,k;
    20 int cnt=1;
    21 bool win[MAX_L];
    22 bool lose[MAX_L];
    23 string s[MAX_N];
    24 Node node[MAX_L];
    25 
    26 void read()
    27 {
    28     cin>>n>>k;
    29     for(int i=1;i<=n;i++)
    30     {
    31         cin>>s[i];
    32     }
    33 }
    34 
    35 void init_trie()
    36 {
    37     for(int i=1;i<=n;i++)
    38     {
    39         int now=1;
    40         for(int j=0;j<s[i].size();j++)
    41         {
    42             if(!node[now].nex[s[i][j]-'a'])
    43             {
    44                 node[now].nex[s[i][j]-'a']=++cnt;
    45             }
    46             now=node[now].nex[s[i][j]-'a'];
    47         }
    48     }
    49 }
    50 
    51 void dfs(int now)
    52 {
    53     win[now]=lose[now]=false;
    54     bool flag=true;
    55     for(int i=0;i<26;i++)
    56     {
    57         if(node[now].nex[i])
    58         {
    59             dfs(node[now].nex[i]);
    60             win[now]|=(!win[node[now].nex[i]]);
    61             lose[now]|=(!lose[node[now].nex[i]]);
    62             flag=false;
    63         }
    64     }
    65     if(flag) lose[now]=true;
    66 }
    67 
    68 void work()
    69 {
    70     init_trie();
    71     dfs(1);
    72     if(win[1] && !lose[1]) cout<<((k&1)?"First":"Second")<<endl;
    73     else if(win[1] && lose[1]) cout<<"First"<<endl;
    74     else cout<<"Second"<<endl;
    75 }
    76 
    77 int main()
    78 {
    79     read();
    80     work();
    81 }
  • 相关阅读:
    学习Spring Cloud中eureka注册中心添加security认证,eureka client注册启动报错
    MySQL 建索引时 Specified key was too long; max key length is 767 bytes 错误的处理
    python3.x运行的坑:AttributeError: 'str' object has no attribute 'decode'
    CENTOS7下安装REDIS
    ubuntu 安装net-tools
    awk命令应用
    shell简单的循环
    Leetcode 713 Subarray Product Less Than K (子数组乘积大于K的个数) (双指针)
    Leetcode 77 Combinations (Backtracking)
    Leetcode 1052 Grumpy Bookstore Owner. (滑动窗口)
  • 原文地址:https://www.cnblogs.com/Leohh/p/8243996.html
Copyright © 2011-2022 走看看