题解/算法 {3186. 施咒的最大总伤害}
@LINK: https://leetcode.cn/problems/maximum-total-damage-with-spell-casting/
;
这个题啊 他卡时间…
很容易想到DP求解, 用map<int,int> Cont
来存储 然后配合DFS记忆化, 求最大值, 普普通通的DP题
long long maximumTotalDamage(vector<int>& A) {
map<int,int> Cont;
for( auto i : A){ Cont[i] ++;}
unordered_map<int,long long> REC;
auto Dfs = [&]( auto _dfs, int _a)->long long{
if( REC.count( _a) > 0){
return REC[_a];
}
long long ANS = 0;
{
auto it = Cont.lower_bound( _a+1);
if( it != Cont.end()){
ANS = std::max( ANS, _dfs( _dfs, it->first));
}
}
{
long long sum = _a *1LL* Cont[_a];
auto it = Cont.lower_bound( _a+3);
if( it != Cont.end()){
sum += _dfs( _dfs, it->first);
}
ANS = std::max( ANS, sum);
}
REC[ _a] = ANS;
return REC[_a];
};
return Dfs( Dfs, Cont.begin()->first);
}
可是 他超时了…
分析下时间, DP状态有1e5
个, 然后注意 不仅lower_bound
还有REC[]
他俩都是log
级别的, 按理说没事, 可力扣他的测试数据 是算在同一个程序的时间 总之他时间限制太严格…
优化吧…
我们把这个lower_bound
优化掉 就需要把之前 DP状态里是存的数值 即map
里的元素, 把他变成下标[0, 1e5)
;
借助vector
的一个构造函数 vector( mp.begin(), mp.end())
他存的是pair
即键值对;
于是 我们找> cur+2
的元素, 就直接通过下标判断 要么是ind+1/ ind+2
;
别忘了REC[]
下标操作, 之前他是map
现在变成数组;
long long maximumTotalDamage(vector<int>& A) {
vector< pair<int,int> > C;
{
map<int,int> Cont;
for( auto i : A){ Cont[i] ++;}
C = vector< pair<int,int> >( Cont.begin(), Cont.end());
}
int N = C.size();
static long long REC[int(1e5)+5];
std::memset( REC, -1, sizeof(REC[0])*N);
auto Dfs = [&]( auto _dfs, int _ind)->long long{
if( REC[_ind] == -1){
REC[ _ind] = 0;
{ // no
if( _ind + 1 < N){
REC[_ind] = max( REC[_ind], _dfs( _dfs, _ind+1));
}
}
{ // yes
long long v = C[_ind].first*1LL*C[_ind].second;
FOR_( i, _ind+1, N-1){
if( C[i].first - C[_ind].first > 2){
v += _dfs(_dfs,i);
break;
}
}
REC[ _ind] = std::max( REC[ _ind], v);
}
}
return REC[_ind];
};
return Dfs( Dfs, 0);
}
但是把, 他又超时了… 理论上分析 他就是1e5
啊, 可能是因为递推的缘故, 你的auto _dfs
要写成引用的方式 即auto & _dfs
才可以;