5884. 解出数学表达式的学生分数(区间dp)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5884. 解出数学表达式的学生分数(区间dp)相关的知识,希望对你有一定的参考价值。

5884. 解出数学表达式的学生分数(区间dp)

  • 先找到每个+的位置,然后合并所有两个加号之间的运算数,最后求和可以得到贡献为5的值 g o a l goal goal

  • 然后就是一个区间 d p dp dp的裸题了,令 d p ( i , j ) dp(i,j) dp(i,j)表示区间[i,j]对应的表达式的结果,注意这里的端点都是运算数,一维枚举长度,一维枚举起点,一维枚举区间分割点.

  • 时间复杂度: O ( n 3 ) O(n^3) O(n3)

  • C++ C o d e Code Code

class Solution {
public:
    unordered_set<int>st[34][34];
    int scoreOfStudents(string s, vector<int>& b) {
        int goal=0,n=s.size();
        vector<int>pl;
        pl.push_back(-1);
        for(int i=1;i<n;i+=2)
            if(s[i]=='+') pl.push_back(i);
        pl.push_back(n);
        for(int i=0;i+1<pl.size();i++){
            int l=pl[i]+1,r=pl[i+1]-1;
            int tmp=1;
            for(int j=l;j<=r;j+=2)  tmp*=s[j]-'0';
            goal+=tmp;
        }
        printf("goal=%d\\n",goal);
        for(int i=0;i<n;i+=2) st[i][i].insert(s[i]-'0');
        for(int k=3;k<=n;k+=2){
            for(int l=0;l+k-1<n;l+=2){
                int r=l+k-1;
                for(int j=l+1;j<r;j+=2){
                    for(int x:st[l][j-1]){
                        for(int y:st[j+1][r]){
                            if(s[j]=='+'&&x+y<=1000) st[l][r].insert(x+y);
                            else if(s[j]=='*'&&x*y<=1000) st[l][r].insert(x*y); 
                        }
                    }
                }
            }
        }
        int ans=0;
        for(int x:b){
            if(x==goal) ans+=5;
            else if(st[0][n-1].count(x)) ans+=2;
        } 
        return ans;
    }
};

以上是关于5884. 解出数学表达式的学生分数(区间dp)的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法之深入解析“解出数学表达式的学生分数”的求解思路与算法示例

BZOJ 2298 problem a(区间DP)

加分二叉树

『字符合并 区间dp 状压dp』

553. 最优除法(区间dp & 数学)

BZOJ4565HAOI2016字符合并 [状压DP][区间DP]