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;
}
};