zoukankan      html  css  js  c++  java
  • [杂题]:staGame(博弈论+Trie树+DFS)

    题目描述

    $pure$和$dirty$决定玩$T$局游戏。对于每一局游戏,有$n$个字符串,并且每一局游戏由$K$轮组成。具体规则如下:在每一轮游戏中,最开始有一个空串,两者轮流向串的末尾添加一个字符,并且需要保证该串为$n$个字符串中任意一个串的前缀,不能操作的人输掉这一轮,并且在下一轮游戏中由该轮输掉的人先手。另外为了遵循女士优先的原则,在每一局游戏的第一轮均由$pure$先手。
    玩家的目标是获得整局游戏的胜利,一局游戏的胜利条件是:对手输掉最后一轮游戏。我们可以假定$pure$和$dirty$都足够聪明。
    现在,对于每一局游戏,$pure$想知道获胜者是谁。


    输入格式

    第一行一个整数$T$,表示游戏局数。
    接下来$T$组数据,每组数据第一行两个整数$n,K$,表示字符串数和轮数,接下来$n$行,每行一个字符串。


    输出格式

    对于每一局游戏,输出一行$"Pure"$或者$"Dirty"$表示获胜者。


    样例

    样例输入:

    2
    2 3
    a
    b
    1 2
    ab

    样例输出:

    Pure
    Dirty


    数据范围与提示

    对于$10\%$的数据,字符串总长不超过$5$,且$Kleqslant 2$;
    对于$20\%$的数据,字符串总长不超过$5$;
    对于另外$20\%$的数据,$K=1$;
    对于$100\%$的数据,$1leqslant nle 10^5;1leqslant Kleqslant 10^9; 1leqslant Tleqslant 10$,每局游戏字符串总长不超过$10^5$,其中字符串非空且均为小写英文字母。


    题解

    这也许是我写的第一篇有关博弈论的题解。

    我们先将所有的串建在$Trie$树上,那么如果你选了某个叶子节点,那么你就赢了;否则你就输了。

    也就是在$Trie$树上跑一个$DFS$即可求出答案。

    听起来是不是很简单?

    时间复杂度:$Theta(sum S)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    int n,K;
    char ch[100001];
    int trie[100001][30],cnt;
    int ans[100001];
    void pre_work()
    {
    	cnt=1;
    	memset(trie,0,sizeof(trie));
    	memset(ans,0,sizeof(ans));
    }
    void insert(char *str)
    {
    	int len=strlen(ch+1),p=1;
    	for(int i=1;i<=len;i++)
    	{
    		int c=str[i]-'a'+1;
    		if(!trie[p][c])trie[p][c]=++cnt;
    		p=trie[p][c];
    	}
    }
    void dfs(int x)
    {
    	bool flag=0;
    	for(int i=1;i<=26;i++)
    		if(trie[x][i])
    		{
    			dfs(trie[x][i]);
    			flag=1;
    			ans[x]|=(ans[trie[x][i]]^3);
    		}
    	if(!flag)ans[x]=1;
    }
    int main()
    {
    	int T;scanf("%d",&T);
    	while(T--)
    	{
    		pre_work();
    		scanf("%d%d",&n,&K);
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%s",ch+1);
    			insert(ch);
    		}
    		dfs(1);
    		if(ans[1]==3||(ans[1]==2&&(K&1)))puts("Pure");
            else puts("Dirty");
    	}
    	return 0;
    }
    

    rp++

  • 相关阅读:
    我回来了
    wget 官方jdk
    linux rpm命令安装卸载 初步使用
    关于一些对location认识的误区(转)
    直接插入排序
    冒泡排序
    Wireshark下TCP三次握手四次挥手
    linux内存使用率详解
    Linux下硬盘使用率详解及shell脚本实现
    Linux下CPU使用率详解
  • 原文地址:https://www.cnblogs.com/wzc521/p/11604111.html
Copyright © 2011-2022 走看看