Codeforces Gym 100500A Poetry Challenge (博弈论基础题)

Codeforces Gym 100500A Poetry Challenge (博弈论基础题)


Problem A. Poetry Challenge
Program: poetry.(c|cpp|java)
Input: poetry.in

Let’s check another challenge of the IBM ICPC Chill Zone, a poetry challenge. One says a poetry string
that starts with an English letter and ends with an English letter, the second should say a poetry string
that starts with the same letter that the previous string ended with.
Given the two poetry string sets representing the known strings for each player. Each player can use each
of his strings only once. If during the player turn he can not say any string, he loses. Assuming both
players play optimally well determine which player wins the game depending on the given two sets.

Input

The first line contains an integer T represent the number of the following test cases.
Each test case starts with an integer n the number of strings in the first player set. Each of the next n
lines contains a string of the first player set. Then read an integer m, which will be succeeded by m lines
describing the strings of the second player. No string in the input will start or finish with a white space,
only lowercase letters. The length of each string in the input will not exceed 10,000 letters.
1 ≤ n ≤ 9
1 ≤ m ≤ 9
1 ≤ T ≤ 10

Output
For each test case, print one line saying which player should win if they are so clever to play it perfectly
and assuming that each one knows the set of the other player.
Discarding quotes, print "Game_i:_player1"to denote the wining of the first player or
"Game_i:_player2"to denote the win of the second player where ‘i’ represents the game number starting
from 1. Replace the underscores with spaces.

Examples

Input:
2
3
a poetry string
a poetry string starting with a
a poetry string ending with a
3
generated word
a word ending with b
poetry
2
either one or two
random string
3
another test case
one greatest poetry
be the winner

Output:
Game 1: player2

Game 2: player1


题意:两人进行博弈,第一个人有n个字符串,第二个人有m个字符串。两个人轮流从各自的字符串中选择一个字符串进行接龙,谁先无法完成接龙谁就算输。


做法: 典型的博弈论题目,DFS枚举寻找下一个人的必败态,作为自己当前的必胜态。注意两个记忆化,不要说重复的话,并且记录已经计算过的答案,避免重复计算


/* written by tomriddly*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 33;
char a[10001];
typedef pair<int, int> pii;
vector<pii> word[2][MAXN];
int n, m, f[2][MAXN];;
bool vis[2][MAXN << 1];
inline bool dfs(const bool &first, const int &n)
{
    // system("pause");
    if (f[first][n] != -1)
        return f[first][n];
    for (int i = 0; i < word[first][n].size(); i++)
        if (!vis[first][word[first][n][i].second])
        {
            vis[first][word[first][n][i].second] = true;
            //printf("%d %d %d", f, n, first[n][i].first);
            if (!dfs(!first, word[first][n][i].first))
            {
                vis[first][word[first][n][i].second] = false;
                return f[first][n] = true;
            }
            vis[first][word[first][n][i].second] = false;
        }
    return f[first][n] = false;
}

int main()
{
    int fuck;
    scanf("%d", &fuck);
    for (int cas = 1; cas <= fuck; cas++)
    {
        memset(vis, false, sizeof(vis));
        memset(f, -1, sizeof(f));
        for (int i = 0; i < 26; i++)
            word[0][i].clear(), word[1][i].clear();
        int cnt = 0;
        scanf("%d\n", &n);
        for (int i = 1; i <= n; i++)
        {
            gets(a);
            word[1][a[0] - 'a'].push_back(pii(a[strlen(a) - 1] - 'a', cnt++));
        }
        scanf("%d\n", &n);
        for (int i = 1; i <= n; i++)
        {
            gets(a);
            word[0][a[0]- 'a'].push_back(pii(a[strlen(a) - 1] - 'a', cnt++));
        }
        bool win = false;
        for (int i = 0; i < 26 && !win; i++)
            if (word[1][i].size())
                win |= dfs(true, i);
        if (win)
            printf("Game %d: player1\n", cas);
        else
            printf("Game %d: player2\n", cas);
    }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值