1.7 acwing.1225. 正则问题 第八届蓝桥杯省赛C++A组,第八届蓝桥杯省赛JAVAA组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 考虑一种简单的正则表达式: 只由 x ( ) | 组成的正则表达式。 小明想求出这个正则表达式能接受的最长字符串的长度。 例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是: xxxxxx,长度是6 。 输入格式 一个由x()|组成的正则表达式。 输出格式 输出所给正则表达式能接受的最长字符串的长度。 数据范围 输入长度不超过100 ,保证合法。 输入样例: ((xx|xxx)x|(x|xx))xx 输出样例: 6
思路:
这两题都与数论无关。
本题考察递归 ,应当放在第一讲。
题意是求在规则之下的xxxxx…的最大长度。
规则1:() 的意思是有括号的先算括号里面的,优先级最高,把括号计算的结果在和括号外的字符拼接,即括号是相对独立,完整的个体
规则2:|的意思是|这个符号两侧的字符串只能选其中一个,由于这题要求能拼接的字符串最长,因此应该选择字符|字符串xxx…长度较大的一侧
再次强调,所有递归问题都可以画一棵递归搜索树来帮助理解。
代码·:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import java.util.Scanner;class Main { static String str; static int k = 0 ; public static void main (String[] args) { Scanner s = new Scanner(System.in); str = s.next(); System.out.println(dfs()); } public static int dfs () { int res = 0 ; while (k < str.length()){ if (str.charAt(k) == '(' ){ k++; res += dfs(); k++; } else if (str.charAt(k) == '|' ){ k++; int t = dfs(); res = res > t ? res : t; } else if (str.charAt(k) == ')' ) break ; else { k++; res++; } } return res; } }
1.8 acwing.1225. 正则问题(巨难) 第十届蓝桥杯省赛C++A组,第十届蓝桥杯省赛JAVAA组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 糖果店的老板一共有 M 种口味的糖果出售。 为了方便描述,我们将 M 种口味编号 1 ∼M。 小明希望能品尝到所有口味的糖果。 遗憾的是老板并不单独出售糖果,而是 K 颗一包整包出售。 幸好糖果包装上注明了其中 K 颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。 给定 N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。 输入格式 第一行包含三个整数 N,M,K。 接下来 N 行每行 K 这整数 T1,T2,⋅⋅⋅,TK,代表一包糖果的口味。 输出格式 一个整数表示答案。 如果小明无法品尝所有口味,输出 −1 。 数据范围 1 ≤N≤100 ,1 ≤M,K≤20 ,1 ≤Ti≤M输入样例: 6 5 3 1 1 2 1 2 3 1 1 3 2 3 5 5 4 2 5 1 2 输出样例: 2
思路:
本题也是考察递归 ,自我感觉难度比较大。
观前提示:第一次接触的铁汁需要高能预警,全程信息密度超大需要反复听!!!(每看一遍都有新的收获)
重复覆盖问题。
大致顺序:先枚举可选择数最少的一列,然后再在这一列中枚举选择哪一行。
三个优化方向:迭代加深—>枚举可选择数最少的列—>可行性剪枝。
其中迭代加深与可行性剪枝合起来称为IDA*算法 。(DFS版本的A*算法)
迭代加深的意思也就是在dfs函数中添加一个参数(本题是depth)来控制迭代次数,1次不能搜到答案,参数
+1搜2次,2次不够就3次,直到达到参数的限制范围,如本题糖果包数最多不可能超过m次。这样做的好处是
防止答案在浅层而dfs搜索到很深找不到答案。
可行性剪枝用到的是估价函数h,用来确定答案的下界(至少的方案数)。
本题的各种位运算 的操作也是非常之精妙!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 #include <iostream> #include <cstdio> #include <vector> using namespace std ;const int N=110 , M=1 <<20 ;vector <int > col[N];int n,m,k;int log2[M];int lowbit (int x) { return x & -x; } int h (int state) { int res=0 ; for (int i=(1 <<m)-1 -state;i;i-=lowbit(i)) { int c=log2[lowbit(i)]; res++; for (auto row:col[c]) { i=i&~row; } } return res; } bool dfs (int depth,int state) { if (!depth||h(state)>depth) { return state==(1 <<m)-1 ; } int t=-1 ; for (int i = (1 << m) - 1 - state; i; i -= lowbit(i)) { int c = log2[lowbit(i)]; if (t == -1 || col[t].size() > col[c].size()) t = c; } for (auto row: col[t]) { if (dfs(depth-1 ,state|row)) return true ; } return false ; } int main () { scanf ("%d%d%d" ,&n,&m,&k); for (int i=0 ;i<m;i++) { log2[1 <<i]=i; } for (int i=0 ;i<n;i++) { int state=0 ; for (int j=0 ;j<k;j++) { int c; cin >>c; state=state|1 <<c-1 ; } for (int j=0 ;j<m;j++) { if (state>>j&1 ) { col[j].push_back(state); } } } int depth=0 ; while (!dfs(depth,0 )&&depth<=m) depth++; if (depth>m) depth=-1 ; cout <<depth<<endl ; return 0 ; }