洛谷 P7541 DOBRA 題解
阿新 • • 發佈:2021-10-11
hhh... 我又來寫題解了
solution
題意簡化
一個字串,將所有的 _
替換成大寫字母,使結果字串符合要求:
1、不包含三個連續 母音 或 子音 字母;
2、字串中至少有一個 L
。
求最終字串可能的個數。
看到這道題,即想到了萬能的演算法——搜尋。
從下標 \(0\) 開始,列舉每一個字母。
由於每次列舉的字母與後面的列舉無關,所以這樣搜尋不會出現重複的終串。
在列舉結束時使用 check 檢測是不是合法終串,如果是就是一種情況。
注意:char 陣列不會克隆,需要回溯。
#include#include<bits/stdc++.h> using namespace std; int yy[127]; int check(char ns[]) { bool flag=0; for(int i=0,len=strlen(ns);i<len-2;i++) { if((yy[ns[i]]==1&&yy[ns[i+1]]==1&&yy[ns[i+2]]==1) || ((!yy[ns[i]])&&(!yy[ns[i+1]])&&(!yy[ns[i+2]]))) return -1; if(!flag&&(ns[i]=='L'||ns[i+1]=='L'||ns[i+2]=='L')) flag=true; } return flag; } long long dfs(int i,char ns[]) { if(i==strlen(ns)) return max(check(ns),0); if(check(ns)==-1) return 0; if(ns[i]!='_') return dfs(i+1,ns); //這裡可優化 ;;雖然對結果沒啥影響 long long ans=0; for(char ch='A';ch<='Z';ch++) { ns[i]=ch; ans+=dfs(i+1,ns); } ns[i]='_'; return ans; } int main() { //init yy['A']=yy['E']=yy['I']=yy['O']=yy['U']=1; yy['_']=-1; char chr[1001]; scanf("%s",chr); cout<<dfs(0,chr); return 0; }1
可惜,只會拿到可憐的 \(30\%\) 的分數。
先來算算時間複雜度吧。
對於每次操作,都有每個 _
需要列舉 \(26\) 次,保證最多有 \(10\) 個,所以列舉次數最少 \(10^{26}\) 次方,超時是穩穩的。
所以如何減少時間複雜度呢?
我們可以發現,這道題實際上子音字母之間並沒有區別。同理,對於母音字母也是如此。
所以,可以每次只列舉兩次,對於子音字母的結果乘 \(26-5=21\);母音字母的結果乘 \(5\)。
還有一點要注意,由於 L
會影響結果,所以需要特殊考慮。
總共 \(3\) 次,列舉次數降為 \(10^3\) ,AC 穩穩的。
AC Code:
#include<bits/stdc++.h> using namespace std; int yy[127]; int check(char ns[]) { bool flag=0; for(int i=0,len=strlen(ns);i<len-2;i++) { if((yy[ns[i]]==1&&yy[ns[i+1]]==1&&yy[ns[i+2]]==1) || ((!yy[ns[i]])&&(!yy[ns[i+1]])&&(!yy[ns[i+2]]))) return -1; if(!flag&&(ns[i]=='L'||ns[i+1]=='L'||ns[i+2]=='L')) flag=true; } return flag; } long long dfs(int i,char ns[]) { int len=strlen(ns); while(ns[i]!='_'&&i<len) i++; //可優化遞迴層數,可惜只有100,沒啥用 if(i==len) return max(check(ns),0); if(check(ns)==-1) return 0; long long ans=0; ns[i]='A'; //這裡泛指母音字母 ans+=dfs(i+1,ns)*5; ns[i]='B'; //這裡泛指子音字母 ans+=dfs(i+1,ns)*20; //將 L 特殊考慮,21-1 即為 20 ns[i]='L'; ans+=dfs(i+1,ns); ns[i]='_'; return ans; } int main() { //init yy['A']=yy['E']=yy['I']=yy['O']=yy['U']=1; yy['_']=-1; char chr[1001]; scanf("%s",chr); cout<<dfs(0,chr); return 0; }
從 9 s 降到 30ms,質的提升啊!
求過!