HDU5396——区间DP+排列组合——Expression
http://acm.hdu.edu.cn/showproblem.php?pid=5396
/*
题目大意:给你一些表达式,问你不考虑乘除优先级,问所有可能性之和为多少
比方说 (1+2)+3 1+(2+3) 算不同
定义dp[i][j] 表示从i到j之和
令k为两个表达式之间的符号
如果k为* 状态转移方程
dp[i][j] = (dp[i][j] + dp[i][k]*dp[k+1][j])
两者情况之积 (1+2*3)*(2+3+4) 左边有两种,右边有两种,那么就是四,因为×肯定是最后一步做的
如果k为+/- 状态转移方程
dp[i][j] = (dp[i][j] + dp[i][k]*(j-k-1) + dp[k+1][j]*(k-i))
和的话 (1+2*3) + (2+3+4) 加是最后一步做的,左边的数会加(j-k-1)!次,即右边的全排列的随时可以加,后面同理
最后都要乘以一个组合数comb[j-i-1][k-i]的原因:
假设我左边两个符号是 + * 右边是 + +
在已经确定了什么必须与什么相乘情况下,只能是选左或者选右
就是 (1+2*3)*(2+3+4) 我们假设顺序必须是2*3 然后 1+(2*3) 右边是(2+3)然后(2+3)+4,但是我们2*3之后可以选择右边(2+3)而不选择1+(2*3)那么这些排列情况需要考虑
我们已经知道了左边的乘法必须先于+法,右边的第一个加法先于第二个加法
那么可以看成一共有4个位置我要选择两个位置把第一个放进去并且满足,那第二个是不是已经确定了
----
*+--
*-+-
*--+
-*+-
-*-+
--*+
6种
*/
/************************************************
* Author :Powatr
* Created Time :2015-8-19 12:27:50
* File Name :HDU5396.cpp
************************************************/
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int MAXN = 1e2 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
ll comb[MAXN][MAXN];
ll fac[MAXN];
void inti()
{
for(int i = 0 ; i <= 100; i++){
comb[i][0] = comb[i][i] = 1;
for(int j = 1; j <= i; j++){
comb[i][j] = (comb[i-1][j-1] + comb[i-1][j])%MOD;
}
}
fac[0] = 1;
for(int i = 1; i <= 100; i++){
fac[i] = fac[i-1] * i % MOD;
}
}
int main(){
int n;
char s[MAXN];
int a[MAXN];
ll dp[MAXN][MAXN];
inti();
while(~scanf("%d", &n)){
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
scanf("%s", s+1);
for(int i = n ; i >= 1; i--){
dp[i][i] = a[i];
for(int j = i + 1; j <= n; j++){
dp[i][j] = 0;
for(int k = i; k <= j; k++){
if(s[k] == '*'){
dp[i][j] = (dp[i][j] + dp[i][k]*dp[k+1][j]%MOD*comb[j-i-1][k-i])%MOD;
}
else if(s[k] == '+'){
dp[i][j] = (dp[i][j] + (dp[i][k]*fac[j-k-1] + dp[k+1][j]*fac[k-i])%MOD*comb[j-i-1][k-i])%MOD;
}
else if(s[k] == '-'){
dp[i][j] = (dp[i][j] + (dp[i][k]*fac[j-k-1] - dp[k+1][j]*fac[k-i])%MOD*comb[j-i-1][k-i])%MOD;
}
}
}
}
printf("%I64d\n", (dp[1][n]+MOD)%MOD);
}
return 0;
}

浙公网安备 33010602011771号