动态规划学习(记住动规五部曲)
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
做题的时候一定要遵从这五步来进行,今天学的是
01背包问题
基本题型:有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define bag_weight 4
#define MAX(a,b)((a>b)?(a):(b))
//dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。
void backPack(int* weight, int weightSize, int* costs, int costSize, int bagWeight) {
int** dp = (int**)malloc(weightSize * sizeof(int*));
//for (int i = 0; i < bagWeight; i++)
// dp[i] = (int*)malloc((bagWeight + 1) * sizeof(int));
memset函数用来赋值
//memset(dp, 0, sizeof(int) * weightSize * (bagWeight + 1));
dp = (int**)malloc(weightSize * sizeof(int*));
for (int i = 0; i < weightSize; i++)
dp[i] = (int*)malloc((bagWeight + 1) * sizeof(int));
memset(dp, 0, sizeof(int) * weightSize * (bagWeight + 1));
// 当背包容量大于物品0的重量时,将物品0放入到背包中-->也就是把第一行都赋值成物品0的价值
int i, j;
for (j = weight[0]; j <= bagWeight; j++)
dp[0][j] = costs[0];
//先遍历物品,再遍历重量
for (i = 1; i < weightSize; i++)
for (j = 0; j <= bagWeight; j++)
{
if (j < weight[i])
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = MAX(dp[i - 1][j], dp[i - 1][j - weight[i]] + costs[i]);
}
printf("%d\n", dp[weightSize - 1][bagWeight]);
return;
}
int main() {
int weight[3] = { 1,3,4 };
int costs[3] = { 15,20,30 };
backPack(weight, sizeof(weight) / sizeof(weight[0]), costs, sizeof(costs) / sizeof(costs[0]), bag_weight);
return 0;
}
新学函数:memst
给数组赋值
还有c语言中可以直接用int*来表示一维数组
int**表示二维数组。
敲了个整数拆分问题
题意:给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
#include<stdio.h>
#include<stdlib.h>
int* initDP(int num) {
int* dp = (int*)malloc(sizeof(int) * (num + 1));
int i;
for (i = 0; i < num + 1; i++) {
dp[i] = 0;
}
return dp;
}
int max(int num1,int num2,int num3) {
int tempMax = num1 > num2 ? num1 : num2;
return tempMax > num3 ? tempMax : num3;
}
int integerBreak(int n) {
int* dp = initDP(n);
dp[2] = 1;
int i;
for (i = 3; i <= n; i++) {
int j;
for (j = 1; j < i - 1; j++) {
dp[i] = max(dp[i], j * (i - j), j * dp[i - j]);
}
}
return dp[n];
}
int main() {
int n;
while (scanf("%d", &n) == 1) {
printf("%d", integerBreak(n));
}
return 0;
}