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 }
时间: 2024-10-06 00:45:02

ZOJ 3892 Available Computation Sequence 区间dp的相关文章

ZOJ 3469 Food Delivery(区间DP)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4255 题意:n个人订餐.n个人位于一条线上,饭店也在这条线上.每个人有一个脾气值p.若第i分钟得到他预定的饭不满意度为p*i.送饭人的速度已知.求一种送饭顺序使得总不满意度最小. 思路:设f[i][j][0],f[i] [j][1]分别表示将[i,j]区间的送完,最后停在左边或右边的最小不满意度.那么我们在DPf[i][j][0]时可以从f[i+1][j]进行转 移

POJ 1141 Brackets Sequence (区间dp 记录路径)

题目大意: 给出一种不合法的括号序列,要求构造出一种合法的序列,使得填充的括号最少. 思路分析: 如果只要求输出最少的匹配括号的数量,那么就是简单的区间dp dp[i][j]表示 i - j 之间已经合法了最少添加的括号数. 转移 就是 dp[i] [j] = min  (dp[i+1][j]+1 , dp[ i+ 1] [ k -1 ] + dp[k+1] [j] (i k 位置的括号匹配)) 其次我们要记录路径,你发现  如果 dp [i] [j] 是由 dp [i+1] [j] 转移过来的

ZOJ1463:Brackets Sequence(区间DP)

Let us define a regular brackets sequence in the following way: 1. Empty sequence is a regular sequence. 2. If S is a regular sequence, then (S) and [S] are both regular sequences. 3. If A and B are regular sequences, then AB is a regular sequence. F

poj 1141 Brackets Sequence (区间DP)

Brackets Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 25893   Accepted: 7295   Special Judge Description Let us define a regular brackets sequence in the following way: 1. Empty sequence is a regular sequence. 2. If S is a re

uva1626 poj 1141 Brackets Sequence 区间dp 打印路径

// poj 1141 Brackets Sequence // 也是在紫书上看的一题,uva就是多了一个t组数据. // 经典区间dp // dp(i,j)表示区间[i,j]内所需要增加的括号数目 // 则分为两种情况 // 一种是s[i]和s[j]是匹配的则 // dp[i][j] = min(dp[i][j],dp[i+1][j-1]) // 另外一种情况是不匹配 // dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]){i<k<j}; // 但是无

UVA1626 / ZOJ1463 Brackets sequence 区间DP

简单区间DP (有空串... ...) Brackets sequence Time Limit: 4500MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Let us define a regular brackets sequence in the following way: Empty sequence is a regular sequence. If S is a

ZOJ 3537 Cake 求凸包 区间DP

题意:给出一些点表示多边形顶点的位置(如果多边形是凹多边形就不能切),切多边形时每次只能在顶点和顶点间切,每切一次都有相应的代价.现在已经给出计算代价的公式,问把多边形切成最多个不相交三角形的最小代价是多少. 思路:首先判断多边形是否是凸多边形,之后就是区间dp了. 求出凸包后,按逆时针来看. 设置dp[i][j]为从顶点i到顶点j所围成凸多边形的最优解. 枚举切点k (i < k < j) dp[i][j] = min(dp[i][k] + dp[k][j] + cost[i][k] + c

ZOJ 3537 Cake(凸包+区间DP)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3537 题目大意:给出一些点表示多边形顶点的位置,如果不是凸多边形(凸包)则不能切,直接输出"I can't cut."切多边形时每次只能在顶点和顶点间切,每切一次的花费为 cost(i, j) = |xi + xj| * |yi + yj| % p.问把多边形切成最多个不相交三角形的最小代价是多少. 解题思路:先求出凸包,接着可以用区间DP解决,设dp

HDU 5273 Dylans loves sequence(区间DP)

Dylans loves sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 114    Accepted Submission(s): 59 Problem Description Dylans is given N numbers a[1]....a[N] And there are Q questions. E