hdu5396(区间DP)
题目意思:
给定一个表达式,运算符没有优先级,求不同顺序计算,所有可能的得到的结果之和。
由于运算符没有优先级,所以有多种顺序去计算,设d[i][j]表示[i,j]区间表达式通过不同顺序计算,所以可能得到的结果之和,
枚举最后一次运算符是第t个,有可能是加减乘三种,所以需要不同处理。
最后由于s[i][t],s[t+1][j],内部运算的绝对顺序确定,但是s[i][j]整体的相对顺序还没确定,所以乘上C[t-i][j-i-1].
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #define maxn 150 #define LL long long #define MOD 1000000007 using namespace std; LL s[maxn][maxn]; LL C[maxn][maxn]; LL fac[maxn]; int n; int a[maxn]; char op[maxn]; void init() { fac[0]=1; for(int i=1;i<maxn;i++) { fac[i]=(fac[i-1]*i)%MOD; } C[0][0]=1; for(int j=1;j<maxn;j++) { C[0][j]=1; for(int i=1;i<maxn;i++) { C[i][j]=( (C[i][j-1]+C[i-1][j-1])) %MOD; //²»Ñ¡£¬C[i][j-1],Ñ¡£¬C[i-1][j-1] } } // printf("%lld\n",C[3][6]); } void init1() { memset(s,0,sizeof(s)); } void solve() { for(int tt=1;tt<=n;tt++) for(int i=1;i<=n;i++) { int j=i+tt; if(j>n) continue; for(int t=i;t<=j-1;t++) { if(op[t]=='+') { int k1=fac[t-i]; int k2=fac[j-(t+1)]; LL temp=0; temp = ( (k2*s[i][t])%MOD+(k1*s[t+1][j])%MOD )%MOD; temp = (temp *C[t-i][j-i-1]) %MOD; s[i][j]= (s[i][j]+temp)%MOD; } else if(op[t]=='-') { int k1=fac[t-i]; int k2=fac[j-(t+1)]; LL temp=0; temp = ( (k2*s[i][t])%MOD-(k1*s[t+1][j])%MOD +MOD)%MOD; temp = (temp *C[t-i][j-i-1]) %MOD; s[i][j]= (s[i][j]+temp)%MOD; } else if(op[t]=='*') { LL temp=0; temp =(s[i][t]*s[t+1][j]) % MOD; temp = (temp *C[t-i][j-i-1]) %MOD; s[i][j]= (s[i][j]+temp)%MOD; } } } /* for(int tt=1;tt<=n;tt++) { for(int i=1;i<=n;i++) { int j=i+tt; if(j>n) continue; printf("%lld ",(s[i][j]+MOD)%MOD ); } printf("\n"); }*/ printf("%lld\n",s[1][n]); } int main() { // freopen("test.txt","r",stdin); init(); while(~scanf("%d",&n)) { init1(); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); s[i][i]=a[i]; //printf("%d ",a[i]); } scanf("%s",&(op[1])); // printf("%s\n",&(op[1])); solve(); } return 0; }