S的长度也就16 直接暴力枚举也就2^16...
于是有dfs和dp两种做法:
dfs:
#include <cstdio>
#include <cstring>
char s[20];
int len;
int dfs(int cur, int cnt) {
if(cnt < 0) return 0;
if(cur >= len) {
if(!cnt) return 1;
return 0;
}
int ans = 0;
if(s[cur] == '(') ans = dfs(cur + 1, cnt + 1);
else if(s[cur] == ')') ans = dfs(cur + 1, cnt - 1);
else {
ans += dfs(cur + 1, cnt + 1);
ans += dfs(cur + 1, cnt - 1);
}
return ans;
}
int main() {
while(~scanf("%s", s)) {
len = strlen(s);
printf("%d\n", dfs(0, 0));
}
return 0;
}
dp(n^3 理论上比dfs快许多 OJ上返回一样是0ms):
#include <cstdio>
#include <cstring>
char s[20];
int len;
int solve() {
int dp[20][20][20] = {0};
dp[0][0][0] = 1;
for(int i = len; i > 0; i--) s[i] = s[i - 1];
for(int i = 1; i <= len; i++) {
for(int j = 0; j <= len; j++) {
for(int k = 0; k <= len; k++) {
if(j >= k && s[i] != ')') dp[i][j + 1][k] += dp[i - 1][j][k];
if(j > k && s[i] != '(') dp[i][j][k + 1] += dp[i - 1][j][k];
}
}
}
int ans = 0;
for(int i = 0; i <= len; i++) {
ans += dp[len][i][i];
}
return ans;
}
int main() {
while(~scanf("%s", s)) {
len = strlen(s);
printf("%d\n", solve());
}
return 0;
}
题目:

Accept: 386 Submit: 736
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
给出一个字符串,其中包括3种字符: ‘(‘, ‘)’, ‘?’.其中?表示这个字符可以是’(‘也可以是’)’. 现在给出字符串S,你可以在’?’处填写’(‘ 或者 ‘)’,当然随意填写得到的序列可能是括号不匹配的。例如”(?”,如果你填写’(‘那么”((“是括号不匹配的! 现在你的任务是确定你有多少种填写方案,使得最终的字符串是括号匹配的!2种方案是不同的,当2种方案中至少存在1个填写字符是不同的。 例如,对于”((??))”,我们可以得到2种方案: “((()))”, “(()())”。
Input
数据包含多组测试数据 第一行输入一个字符串S(S的长度不超过16)。
Output
输出一个整数,表示合法的填写方案数。
Sample Input
((??))
Sample Output
2