原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5234
Happy birthday
Problem Description
Today is Gorwin’s birthday. So her mother want to realize her a wish. Gorwin says that she wants to eat many cakes. Thus, her mother takes her to a cake garden.
The garden is splited into n* m grids. In each grids, there is a cake. The weight of cake in the i-th row j-th column is wij kilos, Gorwin starts from the top-left(1,1) grid of the garden and walk to the bottom-right(n,m) grid. In each step Gorwin can go to right or down, i.e when Gorwin stands in (i,j), then she can go to (i+1,j) or (i,j+1) (However, she can not go out of the garden).
When Gorwin reachs a grid, she can eat up the cake in that grid or just leave it alone. However she can’t eat part of the cake. But Gorwin’s belly is not very large, so she can eat at most K kilos cake. Now, Gorwin has stood in the top-left grid and look at the map of the garden, she want to find a route which can lead her to eat most cake. But the map is so complicated. So she wants you to help her.
Input
Multiple test cases (about 15), every case gives n, m, K in a single line.
In the next n lines, the i-th line contains m integers wi1,wi2,wi3,⋯wim which describes the weight of cakes in the i-th row
Please process to the end of file.
[Technical Specification]
All inputs are integers.
1<=n,m,K<=100
1<=wij<=100
Output
For each case, output an integer in an single line indicates the maximum weight of cake Gorwin can eat.
Sample Input
1 1 2
3
2 3 100
1 2 3
4 5 6
Sample Output
0
16
Hint
In the first case, Gorwin can’t eat part of cake, so she can’t eat any cake.
In the second case, Gorwin walks though below route (1,1)->(2,1)->(2,2)->(2,3). When she passes a grid, she eats up the cake in that grid. Thus the total amount cake she eats is 1+4+5+6=16.
题解
做了那么多dp,发现根据数据范围确定dp姿势是非常科学的。。。
那么,这道题的数据范围是100,多半需要用 O ( n 3 ) O(n^3) O(n3)dp,我们再考虑一下题目本身:
我们可以将每个格子看做一个背包,背包的权值为格子里的蛋糕重量。我们先考虑这样一个二维的背包,dp[i][j]可以从上面和左边的点转移过来,如过加上当前点的权值大于上限,那么不吃,反之就吃。但这样实际上是一个贪心策略,很可能无法达到最优解。
但根据数据我们推算出的复杂度明明是 O ( n 3 ) O(n^3) O(n3)啊,所以我们可以再加一维,布尔数组dp[i][j][k]表示在点(i,j)我们可以吃到k千克蛋糕,我们可以这样转移状态:
如果我们吃了这个点的蛋糕,就可以如此转化:
如果没有吃这个点的蛋糕,显然有:
代码
#include<bits/stdc++.h>
using namespace std;
const int M=105;
int n,m,p,val[M][M];
bool dp[M][M][M];
void in()
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
scanf("%d",&val[i][j]),dp[i][j][0]=1;
}
void ac()
{
for(int i=1;i<=m;++i)
dp[0][i][0]=1;
for(int i=1;i<=n;++i)
dp[i][0][0]=1;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
for(int k=val[i][j];k<=p;++k)
{
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-val[i][j]]);
dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k-val[i][j]]);
}
for(int k=1;k<=p;++k)
{
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k]);
dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k]);
}
}
for(int i=p;i>=0;--i)
if(dp[n][m][i])
{
printf("%d\n",i);
return;
}
}
int main()
{
while(scanf("%d%d%d",&n,&m,&p)!=EOF)
in(),ac();
return 0;
}