题目大意:过生日,有一个N*M的表格,每个位置都有一块一定重量的蛋糕你可以选择吃完或者不吃,从(1,1)走到(n,m),每次只能向右走或向下走,最多能吃k重量的蛋糕。问你最多能吃多少蛋糕。
题目思路:之前的01背包我们都是用一维数组v[i]来储存的,但这次要用二维数组Map[i][j]储存一个点的价值,当前点由Map[i][j-1]或Map[i-1][j]走到。
#include<iostream>
#include<algorithm>
#define MAX 105
using namespace std;
int dp[MAX][MAX][MAX], Map[MAX][MAX];//dp[i][j][q]表示在(i,j)处且当前背包大小为q的情况下,i*j个物品最佳组合得到的最大价值
int main()
{
int n, m, k, v1, v2;//k为背包大小
while (scanf_s("%d%d%d", &n, &m, &k) != EOF)//保证循环输入测试用例
{
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
scanf_s("%d", &Map[i][j]);
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
for (int q = 1; q <= k; q++)
{
v1 = max(dp[i][j - 1][q], dp[i - 1][j][q]);
v2 = Map[i][j] + max(dp[i][j - 1][q - Map[i][j]], dp[i - 1][j][q - Map[i][j]]);
if (Map[i][j] > q)
dp[i][j][q] = v1;
else
dp[i][j][q] = max(v1, v2);
}
}
}
printf("%d\n", dp[n][m][k]);
}
system("pause");
return 0;
}