dp[i][j][k]为在点(i,j),当前获得量为k的方法是否存在
要求解点(i,j),有(i-1,j)和(i,j-1)的答案即可得出(因为题目中只允许向下向右走
数据并不强,也并不需要压缩空间
bc上的题解是dp[i][j][k]代表在(i,j)背包容量为k时的最大值,个人认为反而复杂化了问题……
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<stack>
#include<queue>
#include<fstream>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#define CLR(x) memset(x,0,sizeof(x))
#define SETMAX(x) memset(x,0x3f,sizeof(x))
#define SETNO(x) memset(x,-1,sizeof(x))
#define ll long long
#define eps 1e-6
#define pow2(x) ((x)*(x))
#define forto(i,n) for(int i=0;i<n;i++)
#define for1to(i,n) for(int i=1;i<=n;i++)
#define VI vector<int>
using namespace std;
const double PI=acos(-1.0);
#define INF 0x3f3f3f3f
#define NINF 0xbfffffff
using namespace std;
int A[111][111];
bool dp[111][111][111];
int main()
{
cin.sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("test.txt","r",stdin);
#endif // ONLINE_JUDGE
int n,m,K;
while (cin>>n>>m>>K)
{
for1to(i,n)
for1to(j,m)
cin>>A[i][j];
for (int i=0;i<=n;i++)
dp[i][0][0]=true;
for (int i=0;i<=m;i++)
dp[0][i][0]=true;
for1to(i,n)
{
for1to(j,m)
{
for (int k=0;k<=K;k++)
{
dp[i][j][k]=dp[i-1][j][k] || dp[i][j-1][k];
if (k>=A[i][j])
dp[i][j][k] = dp[i][j][k]|| dp[i-1][j][k-A[i][j]] || dp[i][j-1][k-A[i][j]];
}
}
}
for (int i=K;i>=0;i--)
{
if (dp[n][m][i])
{
cout<<i<<endl;
break;
}
}
}
return 0;
}