題解 CodeVS1251 【括號】
阿新 • • 發佈:2020-07-15
題目描述:
計算乘法時,我們可以新增括號,來改變相乘的順序,比如計算 $x_1,x_2,...,x_{n-1},x_n$ 的積,我們可以:
$(x_1(x_2(...(x_{n-1}x_n))))$......$((((x_1x_2)...)x_{n-1})x_n)$
你的任務是程式設計求出所有這樣的添括號的方案。
輸入格式:
輸入檔案第一行是一個數 $n$ $(1<=n<=10)$,表示有 $n$ 個變數,之後 $n$ 行每行一個變數的名字。
輸出格式:
輸出所有的新增括號的方案。注意:單個字元不要加括號,兩個字元相乘中間要有乘號。
題解:
本題不難$dfs$計算答案,難的是輸出答案
我們可以先從如何計算答案入手,易得,區間 $l-r$ 的方法數計算公式為:
$f(l,r)=\sum_{i=l}^{r-1}f(l,i)*f(i+1,r)$
因為答案數是由子區間得來的,所以具體答案也是從子區間得來的,我們可以定義 $ans(l,r,k)$ 為區間 $l$ 到 $r$ 的第 $k$ 個答案。如果我們是使用 $string$ 來記錄答案的話答案的獲得公式即為:
$ans(l,r,x)=ans(l,i,y)+ans(i+1,r,z)$,其中$(l<=i<r)(x,y,z$為任意的存在的答案下標$)$
如果擔心超空間,可以嘗試儲存序號,將“$($”標號為 $11$ ,將“$)$”標號為 $12$ ,將“$*$”標號為 $13$ ,只不過這樣就不能使用優秀的$string$來更新答案了。
程式碼如下:
#include<bits/stdc++.h> using namespace std; int n; string s[15]; vector <string> ans[15][15]; void dfs(int l,int r) { if(ans[l][r].size()) return ; for(int i=l;i<r;++i) { dfs(l,i); dfs(i+1,r); } for(int i=l;i<r;++i) { for(int j=0;j<(int)ans[l][i].size();++j) { for(int k=0;k<(int)ans[i+1][r].size();++k) { ans[l][r].push_back("("+ans[l][i][j]+ans[i+1][r][k]+")"); } } } // printf("%d %d\n",l,r); // for(int i=0;i<(int)ans[l][r].size();++i) // cout<<ans[l][r][i]<<'\n'; return ; } int main() { cin>>n; for(int i=1;i<=n;++i) { cin>>s[i]; ans[i][i].push_back(s[i]); if(i>1) ans[i-1][i].push_back("("+s[i-1]+"*"+s[i]+")"); } dfs(1,n); for(int i=0;i<(int)ans[1][n].size();++i) cout<<ans[1][n][i]<<'\n'; return 0; }