洛谷 P3041 视频游戏的连击Video Game Combos(AC自动机+拓扑排序+数位DP)
洛谷 P3041 視頻游戲的連擊Video Game Combos
難度一般,不過這個數(shù)位DP其實應(yīng)該叫做記憶化搜索
題意:玩游戲時可以通過按鍵組合打出combo技能;然后是已知N個combo的按鍵方式,然后求K次按鍵最多可以放出的combo技能(combo技能之間可以重疊)。
思路:
題目描述
Bessie is playing a video game! In the game, the three letters ‘A’, ‘B’, and ‘C’ are the only valid buttons. Bessie may press the buttons in any order she likes; however, there are only N distinct combos possible (1 <= N <= 20). Combo i is represented as a string S_i which has a length between 1 and 15 and contains only the letters ‘A’, ‘B’, and ‘C’.
Whenever Bessie presses a combination of letters that matches with a combo, she gets one point for the combo. Combos may overlap with each other or even finish at the same time! For example if N = 3 and the three possible combos are “ABA”, “CB”, and “ABACB”, and Bessie presses “ABACB”, she will end with 3 points. Bessie may score points for a single combo more than once.
Bessie of course wants to earn points as quickly as possible. If she presses exactly K buttons (1 <= K <= 1,000), what is the maximum number of points she can earn?
貝西在玩一款游戲,該游戲只有三個技能鍵 “A”“B”“C”可用,但這些鍵可用形成N種(1 <= N<= 20)特定的組合技。第i個組合技用一個長度為1到15的字符串S_i表示。
當(dāng)貝西輸入的一個字符序列和一個組合技匹配的時候,他將獲得1分。特殊的,他輸入的一個字符序列有可能同時和若干個組合技匹配,比如N=3時,3種組合技分別為"ABA", “CB”, 和"ABACB",若貝西輸入"ABACB",他將獲得3分。
若貝西輸入恰好K (1 <= K <= 1,000)個字符,他最多能獲得多少分?
輸入格式
-
Line 1: Two space-separated integers: N and K.
-
Lines 2…N+1: Line i+1 contains only the string S_i, representing combo i.
輸出格式
- Line 1: A single integer, the maximum number of points Bessie can obtain.
輸入輸出樣例
輸入
3 7
ABA
CB
ABACB
輸出
4
說明/提示
The optimal sequence of buttons in this case is ABACBCB, which gives 4 points–1 from ABA, 1 from ABACB, and 2 from CB.
//#pragma comment(linker, "/STACK:102400000,102400000") #include "bits/stdc++.h" #define pb push_back #define ls l,m,now<<1 #define rs m+1,r,now<<1|1 #define hhh printf("hhh\n") #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) using namespace std; typedef long long ll; typedef pair<int,int> pr; inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}const int maxn = 4e2+10; const int mod = 1e4+7; const double eps = 1e-9;char s[maxn]; int N, K; int trie[maxn][26], fail[maxn], cnt; vector<int> refail[maxn]; int in[maxn], num[maxn]; int dp[1010][maxn];void insert() {int len=strlen(s), p=0;for(int i=0; i<len; ++i) {int k=s[i]-'A';if(!trie[p][k]) trie[p][k]=++cnt;p=trie[p][k];}num[p]++; }void build() {queue<int> q;for(int i=0; i<26; ++i) if(trie[0][i]) q.push(trie[0][i]);while(q.size()) {int now=q.front(); q.pop();for(int i=0; i<26; ++i) {if(trie[now][i]) {fail[trie[now][i]]=trie[fail[now]][i];refail[trie[fail[now]][i]].pb(trie[now][i]);in[trie[now][i]]++;q.push(trie[now][i]);}else trie[now][i]=trie[fail[now]][i];}} }void Toposort() {queue<int> q;for(int i=0; i<=cnt; ++i) if(!in[i]) q.push(i);while(q.size()) {int now=q.front(); q.pop();for(int i=0; i<refail[now].size(); ++i) {int v=refail[now][i];num[v]+=num[now];if(--in[v]==0) q.push(v);}} }int dfs(int pos, int now) {if(pos>K) return 0;if(~dp[pos][now]) return dp[pos][now];int ans=0;for(int i=0; i<26; ++i)ans=max(ans,num[trie[now][i]]+dfs(pos+1,trie[now][i]));return dp[pos][now]=ans; }int main() {//ios::sync_with_stdio(false);N=read(), K=read();for(int i=0; i<N; ++i) scanf("%s", s), insert();build();Toposort();memset(dp,-1,sizeof(dp));printf("%d\n", dfs(1,0)); }總結(jié)
以上是生活随笔為你收集整理的洛谷 P3041 视频游戏的连击Video Game Combos(AC自动机+拓扑排序+数位DP)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大气科学需要计算机能力吗,大气科学发表s
- 下一篇: 三容水箱液位控制系统_基于MATLAB三