题目评测(借借DTT的私人题库)
题目描述
有一个n × m的矩阵,你从左上角走到右下角,只能向下和向右走。每个点上有一个重量v i,j 价值w i,j 的物品,你有一个容量为S的背包,经过一个点你可以将此点的物品放入背包,求最大能得到的价值。
输入
输入文件 matrix.in。
第一行三个数n, m, S。
下面n行,每行m个数,第i + 1行第j个数表示v i,j 。
下面n行,每行m个数,第i + n + 1行第j个数表示w i,j 。
输出
输出文件 matrix.out。
一行一个数表示最大的价值。
思路:
状态设置
f[j][k]
其中j代表列数,k代表此时背包的容量
转移方程
f[j][k]=max(max(max(f[j][k-a[i][j].wei]+a[i][j].val,f[j][k]),f[j-1][k]),f[j-1][k-a[i][j].wei]+a[i][j].val);
//尽量别分开,因为f[j][k]的值会有所改变
输出
由于f[m][s]代表的不一定是最大值,所以我们不能直接输出f[m][s],我们还应该进行比较不同背包容量的值,而不用枚举不同位置的值,因为在DP中我们已经对其进行了处理,所以ans的输出也是要考虑的
样例输入
3 4 5
1 2 1 1
2 3 1 2
3 2 2 2
2 3 4 2
1 4 5 1
10 1 2 1
样例输出
14
代码
#includeusing namespace std; int n,m,s; int f[450][450]; int ans=0; int scan() { int as=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') { as=(as<<3)+(as<<1)+c-'0'; c=getchar(); } return as; } struct ss { int val,wei; }a[405][405]; int main() { n=scan(); m=scan(); s=scan(); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) a[i][j].wei=scan(); } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) a[i][j].val=scan(); } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { for(int k=s;k>=0;k--) { if(k>=a[i][j].wei) { f[j][k]=max(max(max(f[j][k-a[i][j].wei]+a[i][j].val,f[j][k]),f[j-1][k]),f[j-1][k-a[i][j].wei]+a[i][j].val); } else f[j][k]=max(f[j-1][k],f[j][k]); } } } for(int i=0;i<=s;i++) { ans=max(ans,f[m][i]); } cout<<ans; return 0; }