1. 0-1背包问题
1)动态规划法
经典的01背包裸题一般都是这个方法很快敲出来的。
#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
int w[35000],d[35000],dp[35000];
int main()
{
int n,m; //n是物品个数,m是背包最大承重或者说容量
while(scanf("%d%d",&n,&m)!=EOF) {
for(int i=1;i<=n;i++)
scanf("%d%d",&w[i],&d[i]);
for(int i=1;i<=n;i++)
for(int j=m;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+d[i]);
printf("%d\n",dp[m]);
}
return 0;
}
前身:
这种方法我觉得是更好理解的,他是第一种方法的未优化空间版本,容易超空间…
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int N,W; //N物品个数,W承重或容量
int results[13500][13000];
int w[13500],v[13500]; //weight and value
int main(int argc, char *argv[]) {
while(scanf("%d%d",&N,&W)!=EOF) {
for(int i=1;i<=N;i++)
scanf("%d%d",&w[i],&v[i]);
for (int i = 1; i <= N; i++)
for (int j = 1; j <= W; j++) {
if (j < w[i]) // 装不进去
results[i][j] = results[i-1][j];
else // 容量足够
results[i][j] = max( results[i-1][j],results[i-1][j-w[i]] + v[i] );
}
for(int i=0;i<=N;i++) {
cout<<endl;
for(int j=0;j<=W;j++)
printf("%-4d ",results[i][j]);
}
}
}
2)分治法
同时也记录一下分治法,最小生成树-Kruskal(克鲁斯卡尔)算法的思想。有些问题会超时,毕竟是递归。
int ks(int i, int c){ //i是物品个数,c是背包容量
int result = 0;
if (i == 0 || c == 0){
// 初始条件
result = 0;
} else if(ws[i] > c){
// 装不下该珠宝
result = ks(i-1, c);
} else {
// 可以装下
int tmp1 = ks(i-1, c);
int tmp2 = ks(i-1, c-ws[i]) + vs[i];
result = max(tmp1, tmp2);
}
return result;
}