ZOJ-3892- Available Computation Sequence【区间dp】

来源:互联网 发布:大数据时代的教育 编辑:程序博客网 时间:2024/06/03 15:29

ZOJ-3892- Available Computation Sequence


                        Time Limit: 2 Seconds      Memory Limit: 65536 KB

Keine is a teacher and recently she is preparing the test paper of the mid-term test of mathematics. The main content is the vector operation. She has already made some formulas before. Those formulas are about the most common vector operations:
Scalar multiplication ‘’ : number vector = vector, vector * number = vector, number * number = number
Dot product ‘.’ : vector . vector = number.
Cross product ‘^’ : vector ^ vector = vector.
In Gensokyo, there is another amazing operation:
Gensokyo product ‘!’: number ! number = number ! vector = vector ! number = vector, vector ! vector = number.
这里写图片描述
Unfortunately Keine forgot to add brackets before printing the test paper. What’s worse is that she hasn’t teached her students the priority of these four operations. So she thinks it’s necessary to prepare all possible answers. Now she wants to know the number of available compuation sequences and requires your help.

You don’t want to be CAVED, do you?

Input

There are multiple cases.
The first line of input is an integer n (1 ≤ n ≤ 20) which indicates the cases of test data.
The following n lines each contain a nonempty string consisted of ‘*’, ‘.’, ‘^’, ‘!’, lower letters and digits. The length of each string will be less than 105.
The meaning of ‘‘, ‘.’ ‘^’ and ‘!’ are described above. There are at most 100 operators(‘‘, ‘.’, ‘^’, ‘!’). Consecuive letters represent a vector and consecutive digits represent a number.
It is confirmed that operators are not adjacent. There is always an operator between vector and number.

Output

For each case, please output the number of available computation sequences. It may be very large, so you must output the answer modulo 109 + 7.

Sample Input

4
32*x
x*x
1*x^x
1!x!2!b

Sample Output

1
0
2
5

Hint

The five computation sequences of the 4th sample are listed below:

(((1!x)!2)!b)
((1!x)!(2!b))
((1!(x!2))!b)
(1!((x!2)!b))
(1!(x!(2!b)))

If we use permutations to represent computation sequences, then 132 and 312 will be regarded as the same (the 2nd sequence).

题目链接:ZOJ 3892

题目大意:给定一个由运算符、数字、字母组成的字符串,单词表示矢量,有数乘、点乘、叉乘和一个特殊运算符混合运算。求合法的计算顺序总数。

题目思路:根据本题计算顺序的定义,(a+b)(c+d)的运算顺序是唯一的。非常显然的区间动态规划。设f[i][j]为区间[i, j]上的运算顺序,则有f[i][j] = Sigma(f[i][k] f[k + 1][j]){i <= k < j}

  • dp[i][j][0]表示第i位到第j位,运算结果为0的情况数
  • dp[i][j][1]表示第i位到第j位,运算结果为1的情况数

一、首先简化给出的算式,0表示数字,1表示字母,运算符号照常。最后得到一串只含0,1,运算符号的字符串

二、接下来区间dp分别判断4种运算符号的情况,根据题意可得:

'*':    number(0): num * num    vector(1): num * vec | vec * num'.':    number(0): vec.vec    vector(1): none'^':    number(0): none    vector(1): vec ^ vec'!':    number(0): vec ! vec    vector(1): num ! num | vec ! num | num ! vec

以下是代码:

#include <vector>#include <map>#include <set>#include <algorithm>#include <iostream>#include <cstdio>#include <cmath>#include <cstdlib>#include <string>#include <cstring>using namespace std;#define mod 1000000007long long dp[300][300][2];  int main(){    int t;    cin >> t;    while(t--)    {        memset(dp,0,sizeof(dp));        string s,ret,ans="";        s.clear();        ans.clear();        cin >> s;        for (int i = 0; i < s.size(); i++)        {                   if (s[i] != '*' && s[i] != '!' && s[i] != '^' && s[i] != '.')            {                ret += s[i];            }            else            {                if (isdigit(ret[0])) ans += "0";                else ans += "1";                ans += s[i];                ret.clear();            }        }        if (isdigit(ret[0])) ans += "0";        else ans += "1";        for (int i = 0; i < ans.size(); i += 2)        {            if (ans[i] == '0')                dp[i][i][0] = 1;            else                dp[i][i][1] = 1;        }        for (int j = 0; j < ans.size(); j+=2)        {            for (int i = j; i >= 0; i-=2)            {                for (int k = i+1; k < j; k += 2)                {                    if (ans[k] == '*')                    {                        dp[i][j][0] = (dp[i][j][0] + (dp[i][k-1][0] * dp[k+1][j][0]) % mod) % mod;                        dp[i][j][1] = (dp[i][j][1] + (dp[i][k-1][0] * dp[k+1][j][1] % mod + dp[i][k-1][1] * dp[k+1][j][0] % mod)) % mod;                    }                    else if (ans[k] == '.')                    {                        dp[i][j][0] = (dp[i][j][0] + (dp[i][k-1][1] * dp[k+1][j][1]) % mod) % mod;                    }                    else if (ans[k] == '^')                    {                        dp[i][j][1] = (dp[i][j][1] + (dp[i][k-1][1] * dp[k+1][j][1]) % mod) % mod;                    }                    else                    {                        dp[i][j][0] = (dp[i][j][0] + (dp[i][k-1][1] * dp[k+1][j][1]) % mod) % mod;                        dp[i][j][1] = (dp[i][j][1] + (dp[i][k-1][0] * dp[k+1][j][0]) % mod + (dp[i][k-1][0] * dp[k+1][j][1]) % mod + (dp[i][k-1][1] * dp[k+1][j][0]) % mod) % mod;                      }                }            }        }        long long last = (dp[0][ans.size()-1][1] + dp[0][ans.size()-1][0])%mod;        cout << last << endl;    }    return 0;                                                                  }
1 0
原创粉丝点击