我想写几个关于背包问题的的小模板,在蓝桥之前我在我电脑word写过一个,但莫名其妙的就没了,所以我想在这再写一次,比如说我们常见的完全背包,01背包还有,多维数组背包,其实我的想法背包都是一个体积是V的大包,现在有多个不同体积的小包,每个背包的价值不,现在我们要通过代码的形式找到尽可能多的填满背包后大包所产生的价值,价值最小或价值最大。
1.完全背包
for(i = 1 ; i <= n ; ++i){
for(j = w[i] ; j <= f-e ; ++j ){
if(dp[j-w[i]]!=INF)//INF可以当做无穷大
dp[j]=min(dp[j],dp[j-w[i]]+p[i]);
这是关于存钱罐的dp代码,他每一个零钱可以取多次所以我们从每一个零钱的价值开始dp,也就是说从小到大!
2.分组背包
错误代码:
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int a[101][101];
int dp[10001];
int main()
{
int m , n ;//m是课程,n是天数
while(scanf("%d%d",&m,&n)&&m!=0&&n!=0){
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
for(int i = 1; i <= m ; i++)
for(int j = 1; j <=n ;j++)
cin >> a[i][j];
for(int i = 1;i <= m ;i++)
for(int j = 1; j <=n ;j++)
for(int k = n;k>=j;k--)
{
dp[k] = max(dp[k],dp[k-j]+a[i][j]);
}
cout << dp[n] <<endl;
}
}
正确代码:
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int a[101][101];
int dp[10001];
int main()
{
int m , n ;//m是课程,n是天数
while(scanf("%d%d",&m,&n)&&m!=0&&n!=0){
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
for(int i = 1; i <= m ; i++)
for(int j = 1; j <=n ;j++)
cin >> a[i][j];
for(int i = 1;i <= m ;i++)
for(int j = n; j >= 1 ;j--)
for(int k = 1;k<=j;k++)
{
dp[j] = max(dp[j],dp[j-k]+a[i][k]);
}
cout << dp[n] <<endl;
}
}
3.01背包
for(int i = 1 ; i <= N ;i++)
for(int j = V; j >=b[i];j--)
dp[j] = max(dp[j],dp[j-b[i]]+a[i]);
cout << dp[V] <<endl;
01背包中每一个物品只会取一次,所以是从大到小。