ZOJ 3892 Available Computation Sequence 区间dp
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5595
题意:给出n个字符串,里面包含'*', '.', '^', '!'这四个运算符,以及小写字母(表示向量)和数字。
四个运算符都有不同的运算规则。问添上括号后,可以组成多少个不同的算式(不能进行非法运算)。
思路:简单区间DP,把一个运算符看成一位。
dp[i][j][1]表示第i-j位运算结果为数字的情况有多少种。
dp[i][j][0]表示第i-j位运算结果为向量的情况有多少种。
然后进行区间DP,根据中间的运算符选择两边是数字或者向量,避免非法情况。
1 #include <bits/stdc++.h> 2 using namespace std; 3 int T; 4 string s; 5 long long dp[200][200][2]; 6 char op[110]; 7 int mark[110]; 8 const long long mod = 1000000000+7; 9 int main() 10 { 11 scanf("%d", &T); 12 while(T--) 13 { 14 cin>>s; 15 bool fop = false; 16 int cntop = 0, cnt = 0; 17 for(int i = 0; i < s.size(); i++) 18 { 19 if(i == 0) 20 { 21 if(s[0] >= '0' && s[0] <= '9') mark[++cnt] = 1; 22 else if(s[0] >= 'a' && s[0] <= 'z') mark[++cnt] = 0; 23 } 24 else 25 { 26 if(s[i] == '^' || s[i] == '!' || s[i] == '*' || s[i] == '.') 27 { 28 fop = true; 29 op[++cntop] = s[i]; 30 } 31 else 32 { 33 if(fop == true) 34 { 35 if(s[i] >= '0' && s[i] <= '9') mark[++cnt] = 1; 36 else if(s[i] >= 'a' && s[i] <= 'z') mark[++cnt] = 0; 37 fop = false; 38 } 39 else continue; 40 } 41 } 42 43 } 44 memset(dp, 0, sizeof(dp)); 45 for(int i = 1; i <= cnt; i++) 46 { 47 if(mark[i] == 0) dp[i][i][0] = 1; 48 else if(mark[i] == 1) dp[i][i][1] = 1; 49 } 50 51 for(int len = 2; len <= cnt; len++) 52 { 53 for(int i = 1; i <= cnt-len+1; i++) 54 { 55 int j = i+len-1; 56 for(int k = i; k < j; k++) 57 { 58 if(op[k] == '*') 59 { 60 dp[i][j][0] += (dp[i][k][1]*dp[k+1][j][0]%mod+dp[i][k][0]*dp[k+1][j][1]%mod); 61 dp[i][j][0] %= mod; 62 dp[i][j][1] += dp[i][k][1]*dp[k+1][j][1]%mod; 63 dp[i][j][1] %= mod; 64 } 65 else if(op[k] == '^') 66 { 67 dp[i][j][0] += dp[i][k][0]*dp[k+1][j][0]%mod; 68 dp[i][j][0] %= mod; 69 } 70 else if(op[k] == '.') 71 { 72 dp[i][j][1] += dp[i][k][0]*dp[k+1][j][0]%mod; 73 dp[i][j][1] %= mod; 74 } 75 else if(op[k] == '!') 76 { 77 dp[i][j][1] += dp[i][k][0]*dp[k+1][j][0]%mod; 78 dp[i][j][1] %= mod; 79 dp[i][j][0] += dp[i][k][0]*dp[k+1][j][1]%mod + dp[i][k][1]*dp[k+1][j][0]%mod 80 + dp[i][k][1]*dp[k+1][j][1]%mod; 81 dp[i][j][0] %= mod; 82 } 83 } 84 } 85 } 86 long long ans = (dp[1][cnt][0] + dp[1][cnt][1])%mod; 87 printf("%lld\n", ans); 88 89 90 } 91 return 0; 92 }