结论:先空间循环(第二层循环),再物品选取数量循环(第一层循环),空间循环,顺序,逆序随便写,滚动数组,降维数组,随便写。
物品序号 | 物品体积 | 物品价值 | 总体积 | 5 | |||||||
1 | 1 | 1 | 总价值 | 最大 | |||||||
2 | 1 | 2 | |||||||||
3 | 2 | 3 | |||||||||
4 | 2 | 4 | |||||||||
5 | 3 | 5 | |||||||||
6 | 3 | 6 | |||||||||
1.先空间循环(第二层循环),再物品选取数量循环(第一层循环) | |||||||||||
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]) | |||||||||||
dp[i-1][j]表示不选当前序号为i的物品 | |||||||||||
dp[i-1][j-v[i]]+w[i]表示选当前序号为i的物品 | |||||||||||
7(124,34)说明:124表示放了序号为1,2,4的物品;34表示放了序号为3,4的物品 | |||||||||||
选取过程 | dp[序号][体积]=价值 | ||||||||||
序号/体积 | 体积0 | 体积1 | 体积2 | 体积3 | 体积4 | 体积5 | |||||
1 | 0 | 1(1) | 1(1) | 1(1) | 1(1) | 1(1) | dp[1][n+1] | ||||
2 | 0 | 2(2) | 3(12) | 3(12) | 3(12) | 3(12) | dp[2][n+1] | ||||
3 | 0 | 2(2) | 3(12,3) | 5(23) | 6(123) | 6(123) | dp[3][n+1] | ||||
4 | 0 | 2(2) | 4(4) | 6(24) | 7(124,34) | 9(235) | dp[4][n+1] | ||||
5 | 0 | 2(2) | 4(4) | 6(24) | 7(124,34) | 9(235,45) | dp[5][n+1] | ||||
6 | 0 | 2(2) | 4(4) | 6(24,6) | 8(26) | 10(46) | dp[6][n+1] | ||||
m代表物体个数,n代表总体积 | |||||||||||
从上述数据处理过程,可以但看到,数组dp[m+1][n+1]在空间上可以利用滚动数组dp[2][n+1]处理 | |||||||||||
空间明显少了许多 | |||||||||||
序号/体积 | 体积0 | 体积1 | 体积2 | 体积3 | 体积4 | 体积5 | |||||
1 | 0 | 1(1) | 1(1) | 1(1) | 1(1) | 1(1) | dp[0][n+1] | ||||
2 | 0 | 2(2) | 3(12) | 3(12) | 3(12) | 3(12) | dp[1][n+1] | ||||
3 | 0 | 2(2) | 3(12,3) | 5(23) | 6(123) | 6(123) | dp[0][n+1] | ||||
4 | 0 | 2(2) | 4(4) | 6(24) | 7(124,34) | 9(235) | dp[1][n+1] | ||||
5 | 0 | 2(2) | 4(4) | 6(24) | 7(124,34) | 9(235,45) | dp[0][n+1] | ||||
6 | 0 | 2(2) | 4(4) | 6(24,6) | 8(26) | 10(46) | dp[1][n+1] | ||||
继续处理利用dp[n+1]处理,空间足足少了一维,但是处理是逆向的。 | |||||||||||
逆向的原因是,空间小的数据对空间大的数据有影响。空间大的数据对空间小的数据无影响 | |||||||||||
序号/体积 | 体积0 | 体积1 | 体积2 | 体积3 | 体积4 | 体积5 | |||||
0 | 0 | 0 | 0 | 0 | 0 | 第零轮dp[n+1] | |||||
1 | 0 | 1(1) | 1(1) | 1(1) | 1(1) | 1(1) | 第一轮dp[n+1] | ||||
2 | 0 | 2(2) | 3(12) | 3(12) | 3(12) | 3(12) | 第二轮dp[n+1] | ||||
3 | 0 | 2(2) | 3(12,3) | 5(23) | 6(123) | 6(123) | 第三轮dp[n+1] | ||||
4 | 0 | 2(2) | 4(4) | 6(24) | 7(124,34) | 9(235) | 第四轮dp[n+1] | ||||
5 | 0 | 2(2) | 4(4) | 6(24) | 7(124,34) | 9(235,45) | 第五轮dp[n+1] | ||||
6 | 0 | 2(2) | 4(4) | 6(24,6) | 8(26) | 10(46) | 第六轮dp[n+1] | ||||
物品序号 | 物品体积 | 物品价值 | 总体积 | 5 | |||||||
1 | 1 | 1 | 总价值 | 最大 | |||||||
2 | 1 | 2 | |||||||||
3 | 2 | 3 | |||||||||
4 | 2 | 4 | |||||||||
5 | 3 | 5 | |||||||||
6 | 3 | 6 | |||||||||
2.先物品选取数量循环(第二层循环),再空间循环(第一层循环) | |||||||||||
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]) | |||||||||||
dp[i-1][j]表示不选当前序号为i的物品 | |||||||||||
dp[i-1][j-v[i]]+w[i]表示选当前序号为i的物品 | |||||||||||
体积/序号 | 1 | 2 | 3 | 4 | 5 | 6 | |||||
体积0 | 0 | 0 | 0 | 0 | 0 | 0 | |||||
体积1 | 1(1) | 2(2) | 2(2) | 2(2) | 2(2) | 2(2) | |||||
体积2 | 1(1) | 3(12) | 3(12,3) | 4(4) | 4(4) | 4(4) | |||||
体积3 | 1(1) | 3(12,3) | 4(13) | ||||||||
体积4 | 1(1) | ||||||||||
体积5 | 1(1) |
1.先空间循环(第二层循环),空间顺序循环,再物品选取数量循环(第一层循环)
AC代码:
#include <bits/stdc++.h>
#define maxn 110
using namespace std;
int t[maxn],v[maxn],f[maxn][1010];
int main(){
int T,M,i,j;
scanf("%d%d",&T,&M);
for(i=1;i<=M;i++)scanf("%d%d",&t[i],&v[i]);
for(i=1;i<=M;i++)//再物品选取数量循环(第一层循环)
for(j=1;j<=T;j++){//先空间循环(第二层循环),空间顺序循环
f[i][j]=f[i-1][j];//不取当前第i号数据
if(j>=t[i])f[i][j]=max(f[i][j],f[i-1][j-t[i]]+v[i]);//尝试取当前第i号数据
}
printf("%d\n",f[M][T]);
return 0;
}
2.先空间循环(第二层循环),空间逆序循环,再物品选取数量循环(第一层循环)
AC代码:
#include <bits/stdc++.h>
#define maxn 110
using namespace std;
int t[maxn],v[maxn],f[maxn][1010];
int main(){
int T,M,i,j;
scanf("%d%d",&T,&M);
for(i=1;i<=M;i++)scanf("%d%d",&t[i],&v[i]);
for(i=1;i<=M;i++)//再物品选取数量循环(第一层循环)
for(j=T;j>=1;j--){//先空间循环(第二层循环),空间逆序循环
f[i][j]=f[i-1][j];//不取当前第i号数据
if(j>=t[i])f[i][j]=max(f[i][j],f[i-1][j-t[i]]+v[i]);//尝试取当前第i号数据
}
printf("%d\n",f[M][T]);
return 0;
}
3.先空间循环(第二层循环),空间顺序循环,再物品选取数量循环(第一层循环),滚动数组
AC代码:
#include <bits/stdc++.h>
#define maxn 110
using namespace std;
int t[maxn],v[maxn],f[2][1010];
int main(){
int T,M,i,j;
scanf("%d%d",&T,&M);
for(i=1;i<=M;i++)scanf("%d%d",&t[i],&v[i]);
for(i=1;i<=M;i++)//再物品选取数量循环(第一层循环)
for(j=1;j<=T;j++){//先空间循环(第二层循环),空间顺序循环
f[i%2][j]=f[(i-1)%2][j];//不取当前第i号数据
if(j>=t[i])f[i%2][j]=max(f[i%2][j],f[(i-1)%2][j-t[i]]+v[i]);//尝试取当前第i号数据
}
printf("%d\n",f[M%2][T]);
return 0;
}
4.先空间循环(第二层循环),空间逆序循环,再物品选取数量循环(第一层循环),滚动数组
AC代码:
#include <bits/stdc++.h>
#define maxn 110
using namespace std;
int t[maxn],v[maxn],f[maxn][1010];
int main(){
int T,M,i,j;
scanf("%d%d",&T,&M);
for(i=1;i<=M;i++)scanf("%d%d",&t[i],&v[i]);
for(i=1;i<=M;i++)//再物品选取数量循环(第一层循环)
for(j=T;j>=1;j--){//先空间循环(第二层循环),空间逆序循环
f[i%2][j]=f[(i-1)%2][j];//不取当前第i号数据
if(j>=t[i])f[i%2][j]=max(f[i%2][j],f[(i-1)%2][j-t[i]]+v[i]);//尝试取当前第i号数据
}
printf("%d\n",f[M%2][T]);
return 0;
}
5.先空间循环(第二层循环),空间逆序循环,再物品选取数量循环(第一层循环),降维数组
AC代码:
#include <bits/stdc++.h>
#define maxn 110
using namespace std;
int t[maxn],v[maxn],f[1010];
int main(){
int T,M,i,j;
scanf("%d%d",&T,&M);
for(i=1;i<=M;i++)scanf("%d%d",&t[i],&v[i]);
for(i=1;i<=M;i++)//再物品选取数量循环(第一层循环)
for(j=T;j>=1;j--){//先空间循环(第二层循环),空间逆序循环
if(j>=t[i])f[j]=max(f[j],f[j-t[i]]+v[i]);//尝试取当前第i号数据
}
printf("%d\n",f[T]);
return 0;
}
6.先物品选取数量循环(第二层循环),再空间循环(第一层循环),空间顺序循环,
AC代码:
#include <bits/stdc++.h>
#define maxn 110
using namespace std;
int t[maxn],v[maxn],f[maxn][1010];
int main(){
int T,M,i,j;
scanf("%d%d",&T,&M);
for(i=1;i<=M;i++)scanf("%d%d",&t[i],&v[i]);
for(j=1;j<=T;j++)//再空间循环(第一层循环),空间顺序循环
for(i=1;i<=M;i++){//先物品选取数量循环(第二层循环)
f[i][j]=f[i-1][j];//不取当前第i号数据
if(j>=t[i])f[i][j]=max(f[i][j],f[i-1][j-t[i]]+v[i]);//尝试取当前第i号数据
}
printf("%d\n",f[M][T]);
return 0;
}
(此种情况无效)7.先物品选取数量循环(第二层循环),再空间循环(第一层循环),空间逆序循环,
代码如下:
#include <bits/stdc++.h>
#define maxn 110
using namespace std;
int t[maxn],v[maxn],f[maxn][1010];
int main(){
int T,M,i,j;
scanf("%d%d",&T,&M);
for(i=1;i<=M;i++)scanf("%d%d",&t[i],&v[i]);
for(j=T;j>=1;j--)//再空间循环(第一层循环),空间逆序循环
for(i=1;i<=M;i++){//先物品选取数量循环(第二层循环)
f[i][j]=f[i-1][j];//不取当前第i号数据
if(j>=t[i])f[i][j]=max(f[i][j],f[i-1][j-t[i]]+v[i]);//尝试取当前第i号数据
}
printf("%d\n",f[M][T]);
return 0;
}
(此种情况无效)8.先物品选取数量循环(第二层循环),再空间循环(第一层循环),空间顺序循环,滚动数组
代码如下:
#include <bits/stdc++.h>
#define maxn 110
using namespace std;
int t[maxn],v[maxn],f[2][1010];
int main(){
int T,M,i,j;
scanf("%d%d",&T,&M);
for(i=1;i<=M;i++)scanf("%d%d",&t[i],&v[i]);
for(j=1;j<=T;j++)//再空间循环(第一层循环),空间顺序循环
for(i=1;i<=M;i++){//先物品选取数量循环(第二层循环)
f[i%2][j]=f[(i-1)%2][j];//不取当前第i号数据
if(j>=t[i])f[i%2][j]=max(f[i%2][j],f[(i-1)%2][j-t[i]]+v[i]);//尝试取当前第i号数据
}
printf("%d\n",f[M%2][T]);
return 0;
}
(此种情况无效)9.先物品选取数量循环(第二层循环),再空间循环(第一层循环),空间逆序循环,滚动数组
代码如下:
#include <bits/stdc++.h>
#define maxn 110
using namespace std;
int t[maxn],v[maxn],f[2][1010];
int main(){
int T,M,i,j;
scanf("%d%d",&T,&M);
for(i=1;i<=M;i++)scanf("%d%d",&t[i],&v[i]);
for(j=T;j>=1;j--)//再空间循环(第一层循环),空间逆序循环
for(i=1;i<=M;i++){//先物品选取数量循环(第二层循环)
f[i%2][j]=f[(i-1)%2][j];//不取当前第i号数据
if(j>=t[i])f[i%2][j]=max(f[i%2][j],f[(i-1)%2][j-t[i]]+v[i]);//尝试取当前第i号数据
}
printf("%d\n",f[M%2][T]);
return 0;
}
(此种情况无效)10.先物品选取数量循环(第二层循环),再空间循环(第一层循环),空间逆序循环,降维数组
代码如下:
#include <bits/stdc++.h>
#define maxn 110
using namespace std;
int t[maxn],v[maxn],f[1010];
int main(){
int T,M,i,j;
scanf("%d%d",&T,&M);
for(i=1;i<=M;i++)scanf("%d%d",&t[i],&v[i]);
for(j=T;j>=1;j--)//再空间循环(第一层循环),空间逆序循环
for(i=1;i<=M;i++){//先物品选取数量循环(第二层循环)
if(j>=t[i])f[j]=max(f[j],f[j-t[i]]+v[i]);//尝试取当前第i号数据
}
printf("%d\n",f[T]);
return 0;
}