括号,这是一道普通的DFS+字符串处理题,但对于与我这种平时不怎么碰STL的人来说,光是看题解就足足看了半个小时(我有多弱就不解释了吧),最后硬是照着别人的题解才勉强打出来了。
但说实话,这道题带给我的小知识倒真的不少,可以简单的在这列一下(如果有和我一样的难兄难弟可以一起看一下哦!):
1. vector的下标是从 0 开始记录的,而它的size函数则是返回vector内的元素个数,其意是:当你只用push_back函数无脑存储元素时,应当从 0 一直枚举到 size-1 !
2.vector是可以直接用下标访问的!(在代码中可以看到)
3.string可以直接用相加的方式(+) 来合成串!(同样也可以在代码中看到)
4.函数的返回值居然若此多样!
题目分析:
这是一道喊你添加括号的DFS题,那么首当其冲的一步,就是应该先知道怎样添加括号,于是乎,我们觉醒了在小学时学习乘法时的各种经验,便一下得出了以下结论:
1. 对于单独的两个元素(比如 “z" 和 “b”,它们都是在题目中直接给出的数据),要把它们组合成一个串(至少包含两个元素),那么会有:(z*b)
2. 对于一个单独的元素(还是“z“)与一个串(比如简称它为 “h”),要把它们组合成一个更大的串,那么会有:(zh)
3.同2, 对于一个串和另一个串(比如为“c”和“h”),要把它们组合成一个更大的串,那么会有(ch)
然后,在得到了这个结论以后,这一切就没什么好说了,我们的任务就是用DFS顺序来切割子串,贴上借鉴大神的程序,努力分析,一起提升吧(真的是一起么...)!
#include<vector>
#include<cstring>
#include<iostream>
using namespace std;
const int N=10+5;
string str[N];
int n;
vector<string> Dfs(int l,int r){ // 返回值是vector,存放的是当前括号分割下的所有复合串,然后继续搜索,找出所有可能
// Dfs(l,r)表示寻找用在(l,r)的数据集合内括号分割所有可能串,而(1,n)即是我们的最终答案
vector<string> v;
if ( l==r ){ // 特殊情况1:只有一个元素
v.push_back(str[l]);
return v;
}
if ( l+1==r ){ // 特殊情况2:是两个元素结合成串 (即结论1)
string s="("+str[l]+"*"+str[r]+")";
v.push_back(s);
return v;
}
// 正常情况:串与串 或 元素与串 结合(即结论2,3)
for(int cut=l;cut<r;cut++){
vector<string> left=Dfs(l,cut);
vector<string> right=Dfs(cut+1,r);
for(int i=0;i<left.size();i++)
for(int j=0;j<right.size();j++){ // 下标有毒,小心
string s="("+left[i]+right[j]+")";
v.push_back(s);
}// 这里可能会误导大家,但这只是枚举每个左子串和右子串,将它们两两结合,生成所有可能的复合串的操作罢了
}
return v;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>str[i]; // 读入数据串
vector<string> ans=Dfs(1,n); // vector里存放了所有满足括号分割的复合串
for(int i=0;i<ans.size();i++) cout<<ans[i]<<"\n";
return 0;
}
或许下一次我不会写这么多了吧,额嘿嘿(真的多么...)。
2017.1.28