洛谷 P1278 单词游戏

题意

给定 \(n\) 个字符串(\(n\le 16\)) , 每个字符串都由\(5\)种元音字母组成 , 求最长可以接龙拼接的字符串长度

思路

看到\(n\)的范围 \(+\) 字符串的状态为在/不在 , 考虑状态压缩

\(f_{i,j}\)为已接龙状态为\(i\) , 最后字符为\(j\)时的最长长度

首先考虑是否可以递增着往上\(dp\)呢 ? 显然是可以的 , 设\(sta\)为状态 , 那么每次\(sta++\)就行

代码

#include<bits/stdc++.h>
using namespace std;

inline int read() {
    int ans = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')f = -1;
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0') {
        ans = ans * 10 + ch - '0';
        ch = getchar();
    }
    return ans * f;
}
const int N = 19;
int f[1<<N][N];
string s;
int a[N];
char b[N],c[N];
int ans = 0;
int main() {
    int n =read();
    for (int i =1;i<=n;i++) {
        cin>>s;
        a[i] = s.size();
        b[i] = s[s.size()-1];
        c[i] = s[0];
    }
    f[0][0] = 0;
    int p = 2;
    int s = 1;
    for (int i =1; i<= n; i++) {
        f[1<<i-1][i] = a[i];
    }
    for (int i = 3; i<1<<n;i++) {
        while (i >= 1<<p) p++;
        for (int j = 1; j<= p;j++) {
            if (i&1<<j-1) {
                s = i^1<<j-1;
                for (int l = 1; l<= p;l++) {
                    if (!(s&1<<l-1) || b[l]!=c[j])continue;
                    f[i][j] = max(f[i][j],f[s][l] + a[j]);
                    ans = max(ans,f[i][j]);
                }
            }
        }
    }
    cout<<ans;

    return 0;
}
posted @ 2025-04-20 02:05  Guaninf  阅读(4)  评论(0)    收藏  举报