bzoj 2121 DP
首先如果我們能處理出來i,j段能不能消掉,這樣就可以直接dp轉移了,設w[i]為前i為最少剩下多少,那么w[i]=w[j-1] (flag[j][i])。
現在我們來求flag[i][j],首先我們可以把字符串組建立trie然后處理在串L中從left位置開始的所有的flag,那么我們可以在trie上一直往下走,每到一個標記的點就將當前的flag[left][right]設為1,那么這樣可以處理出連續可以消掉的字符串,然后就處理對于類似L為abcde,字符串組為ade,bc這樣可以先消一個,然后再消的情況,這樣我們可以發現,如果對于當前的left,right存在flag[i][right]=1,那么就是這樣的情況,那么我們直接遞歸處理left,i就好了,但是我們發現這里的flag[i][right]的i是大于left的,所以我們在處理以某個為開頭的所有的flag的時候需要倒序處理。
有一個優化,在同一個left時,我們在處理flag的時候有兩種拓展情況,所以對于每一個i我們記錄一個vis[i][j],表示在當前的left,i節點,right為j的情況是否訪問過,這樣有訪問的情況return就好了。
反思:開始沒加優化,挺快就a了,后來加了優化之后,因為我用的指針存的trie,所以vis數組中節點的編號需要對于每個指針都存一個編號,但是這個編號不知道怎么回事兒,一申請就re,后面的按照不加優化的寫,只是在node那在cnt之前申請一個num就會re,在cnt之后申請就沒問題,調了半個上午也不知道怎么回事兒= =,原來一直是這么寫的啊。
反思2:后來發現是return的條件為right>=len,寫成right>len了,這樣就有了未定義行為。
/**************************************************************Problem: 2121User: BLADEVILLanguage: C++Result: AcceptedTime:132 msMemory:158900 kb ****************************************************************///By BLADEVIL #include <cstdio> #include <cstring> #include <algorithm> #define maxn 200 #define maxm 1010using namespace std;struct node{int cnt,num; node *child[30];node(){ cnt=num=0;memset(child,0,sizeof child);} }nodepool[maxm],*totnode,*rot;char s[maxn]; int flag[maxn][maxn],vis[maxn][maxm][maxn],w[maxn]; int n,len;void build_trie(){int j=1;totnode=nodepool; rot=totnode++;scanf("%d",&n);char ch[maxn];while (n--) {scanf("%s",ch);int len=strlen(ch);node *t=rot;for (int i=0;i<len;i++) {if (!t->child[ch[i]-'a']) t->child[ch[i]-'a']=totnode++,t->child[ch[i]-'a']->num=j++;t=t->child[ch[i]-'a'];}t->cnt=1;} }void make(node *rot,int left,int right) {//printf("%d ",rot->num);if (rot->cnt) flag[left][right-1]=1;if (vis[left][rot->num][right]) return ;if (right>=len) return ;vis[left][rot->num][right]=1;if (rot->child[s[right]-'a']) make(rot->child[s[right]-'a'],left,right+1);for (int i=right;i<len;i++) if (flag[right][i]) make(rot,left,i+1); }int main() {scanf("%s",s); len=strlen(s);build_trie();for (int i=len-1;i>=0;i--) make(rot,i,i);/*for (int i=0;i<len;i++) {for (int j=0;j<len;j++) printf("%d ",flag[i][j]);printf("\n");}*/w[0]=0;for (int i=0;i<len;i++) {w[i+1]=w[i]+1;for (int j=0;j<=i;j++) if (flag[j][i]) w[i+1]=min(w[i+1],w[j]);//printf("%d ",w[i]); ????}//printf("\n");printf("%d\n",w[len]);return 0; }?
轉載于:https://www.cnblogs.com/BLADEVIL/p/3591127.html
總結
以上是生活随笔為你收集整理的bzoj 2121 DP的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Basic4android v3.50
- 下一篇: html中可以自定义属性,,,妈的竟然才