I - Shiritori Editorial by llichenyu


English:

My DP is a little different form another Editorial’s.

Note that \(N \le 16\),so we can use Status Compression Dynamic Programming to solve it.

Assuming that \(f_{i,j}\) expresses if we have the status \(i\) and the last letter is \(j\),we can win or lose.

Note that \(f_{i,j}\) could be solved by all \(f_{k,l}\) while \(k\) isn’t belong \(i\) and \(s_k\)’s first letter is \(j\).if we have a \(f_{k,l}\) that \(f_{k,l}=1\),\(f_{i,j}\) will be \(0\),otherwise \(f_{i,j}\) will be \(1\).

Finally,the answer is First only if we have \(f_{2^i,S}=1\) that \(0<i<N\),\(S\) is the last letter in \(s_i\).

And we must DP in reverse order.

Chinese:

我的 DP 跟官方题解的有点不一样。

注意到 \(N \le 16\),所以可以直接状压。

\(f_{i,j}\) 表示状态为 \(i\),最后一个字母是 \(j\) 是否必胜。

枚举不在集合 \(i\) 中的元素 \(k\),如果某一个 \(f_{k,l}=1\),那么 \(f_{i,j}=0\),否则 \(f_{i,j}=1\)

最后,是第一个人胜利当且仅当存在 \(i\),使 \(f_{2^i,S}=1\),其中 \(S\) 表示 \(s_i\) 的末尾字母。

注意要倒着 DP。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int const N=16;
int f[1<<N][27],n;
string s[N];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n;
    for (int i=0;i<n;++i) cin>>s[i];
    for (int i=(1<<n)-1;~i;--i)
        for (int k=0;k<26;++k){
            int flg=1;
            for (int l=0;l<n;++l){
                if ((1<<l)&i) continue;
                if (s[l][0]!='a'+k) continue;
                if (f[i|(1<<l)][s[l][s[l].length()-1]-'a']){flg=0;break;}
            }
            f[i][k]=flg;
        }
    for (int i=0;i<n;++i)
        if (f[1<<i][s[i][s[i].length()-1]-'a']){
            cout<<"First\n";
            return 0;
        }
    cout<<"Second\n";
    return 0;
}

posted:
last update: