对于此数组,每个数字都有选或不选两种选择,现定义数组dp[i][j]表示在前i个数中选择若干个数,这若干个数的总和%3为j的最大值。
对于dp[i][j],任意i对应的x:
不选: dp[i][j]=dp[i-1][j];
此数不选,所以此次状态dp[i][j]和上次状态dp[i-1][j]一样
选:dp[i][j]=dp[i-1][(j-x+3)%3]+x;
此数要选,因为选了一个x,导致现在模3余数为j,这里的j是怎么来的,记上一次选完后的余数为q,j=(q+x)%3->q=(j-x)%3,防止j-x为负数%3出错,先对x%3再加上3后再%即可。
这两种情况取最大值:
dp[i][j]=max(dp[i-1][j],dp[i-1][(j-x%3+3)%3]+x)
在遍历数组时从0开始防止越界可以改为:
dp[i+1][j]=max(dp[i][j],dp[i][(j-x%3+3)%3]+x)
在初始化时,dp[0][0]为0,dp[0][1]和dp[0][2]为-∞,因为这两种是不合法的,没有选数,自然不可能有余数。
class Solution {
public:
int maxSumDivThree(vector<int>& nums) {
int n=nums.size();
int dp[n+1][3];
dp[0][0]=0;
dp[0][1]=INT_MIN;
dp[0][2]=INT_MIN;
for(int i=0;i<n;i++)
{
for(int j=0;j<3;j++)
{
dp[i+1][j]=max(dp[i][j],dp[i][(j-nums[i]%3+3)%3]+nums[i]);
}
}
return dp[n][0];
}
};