416. 分割等和子集
动态规划五部曲:
- dp[i][j]:任取0-i个物品放入容量为j的背包,所能达到的最大价值。本题要求的是任取0-i个物品放入容量为sum/2的背包中,所能达到的最大价值 是否可以等于sum/2。
- 递推公式: max(dp[i-1][j],dp[i-1][j-value[i]]+value[i])
- 初始化:
// 正序遍历
for (int j = nums[0]; j <= sum/2; j++) {
dp[0][j] = nums[0];
}
- 遍历顺序 - 不讲究
- 举例推导dp数组
public static bool CanPartition(int[] nums)
{
int sum = 0;
for (int i = 0; i < nums.Length; i++)
{
sum += nums[i];
}
if (sum % 2 == 1) return false;
int target = sum / 2;
int[,] data = new int[nums.Length, target + 1] ;
for (int j = target; j >= nums[0]; j--)
data[0, j] = nums[0];
for (int i = 1; i < nums.Length; i++)
for (int j = 1; j <= target; j++)
{
if (j < nums[i]) data[i, j] = data[i - 1, j];
else data[i, j] = data[i - 1, j] > data[i - 1, j - nums[i]] + nums[i] ? data[i - 1, j] : data[i - 1, j - nums[i]] + nums[i];
}
if (data[nums.Length - 1, target] == target) return true;
return false;
}