二次元コストのバックパック
01プレミアムパック
そこN項目があり、空き容量がCで、Wは、バックパックの重量容量で、私のスペースのコスト項目としてC [i]は、重量のコストWiは、の値であるVIは、各項目には、一つだけは入れて選択することができますまたはホールドバックパックの最大値にアイテムの和を作るために求めています、
01バックパック:
f[i][j]=max(f[i−1][j],f[i−1][j−w[i]]+v[i])
書き込みの寸法を小さく
for (int i = 1; i <= n; i++)
for (int j = V; j >= w[i]; j--)
f[j] = max(f[j], f[j - w[i]] + v[i])s;
コスト-D
f[i][j][k]=max(f[i−1][j][k],f[i−1][j−c[i]][k-w[i]]+v[i])
私たちの経験に基づいて書くことができます
for(int i=1; i<=n; i++)//枚举物品
for(int j=C; j>=c[i]; j--)//枚举两种状态
for(int k=W; k>=w[i]; k--)
f[j][k]=max(f[j][k],f[j-c[i]][k-w[i]]+v[i]);
実際には、同じ元の状態から複数の変形リュックフルバックパックに新しい制限を追加し、01バックパックは、新しい制限を満たすために寸法を追加し、バックパックのコストは、二次元、2次元であるので、完全なコストに対処することは困難ではありませんバックパック、バックパック2、及び複数のポートフォリオのその他の費用
例
羅バレー1507
ボリュームと限られた重量は、マルチロードいくつかの高カロリー食物条件を担持してみましょう、各食品は一度だけ使用することができます
入力フォーマット:
2つの数の最大量(<400)と最大質量の最初の行(<400)
総食物第二のライン数N(<50)。
第三の行 - 3つの+ N行
各行番号三巻(<400)、質量(<400)カロリー(<500)を含んでいました
出力フォーマット:
(INTの範囲内)を達成することができるカロリーの最大数
#include<bits/stdc++.h>
using namespace std;
int V,M,n;
int v[100],w[100],e[100];//体积,质量,所含卡路里
int f[500][500];
int main()
{
scanf("%d%d%d",&V,&M,&n);
for(int i=1; i<=n; i++)
scanf("%d%d%d",&v[i],&w[i],&e[i]);
for(int i=1; i<=n; i++)//枚举物品
for(int j=V; j>=v[i]; j--)
for(int k=M; k>=w[i]; k--)//枚举两种状态
f[j][k]=max(f[j][k],f[j-v[i]][k-w[i]]+e[i]);
printf("%d",f[V][M]);
return 0;
}
HDU 2159
記事の合計数を制限します
条件費は、このような方法で与えられることができるのみ:M項目の合計を取ることができます
実際には、より多くの等価片の数コストは、各項目の個数のコストは、片コストの最大数はMのために1支払うことができるされています
すべての思考をナップザック、多くの場合、ナップザック問題のうちの2つを解決するために使用することができます
パケットのバックパック
N項目とバックパックの容量Cがあり、私のように空間コストアイテムC [i]は、の値であり、VIは、アイテムがいくつかのグループに分割され、競合アイテムの各グループ、選挙まで、最大値の合計を作ることができるバックパックにアイテムを求めるであろう
問題:これは、グループまたは選択されていないものを選択するのですか?
コストを費やす前に、アイテムのKグループJを最大の価値を得ることができます。f [k]は[J]
f[k][j]=max(f[k−1][j],f[k−1][j−c[i]]+v[i]∣物品i属于组k)
for (所有的组k)
for (int j = V; j >= 0; j--)
for (所有属于组k的i)
f[j] = max{f[j], f[j - c[i]] + v[i]}
例
羅バレー1757
#include <bits/stdc++.h>
using namespace std;
const int M=1010,N=1010;
int n,m;
int f[M],a[N],b[N],c[101][20],cc[101],cn;
int main()
{
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)
{
int C;
scanf("%d%d%d",&a[i],&b[i],&C);
cn=max(cn,C);//cn记录共有几组
cc[C]++;//cc[]记录第C组共有几件物品
c[C][cc[C]]=i;//c[][]记录第C组第i件物品的的序号
}
for(int i=1;i<=cn;i++)//枚举cn个组
for(int j=m;j>=0;j--)//枚举容量
for(int k=1;k<=cc[i];k++)//枚举各组中物品的序号
if(j>=a[c[i][k]])
f[j]=max(f[j],f[j-a[c[i][k]]]+b[c[i][k]]);//套用状态转移方程
printf("%d\n",f[m]);
}
HDU 1712
依存性のバックパック
非ツリー(本体のみメンバー、附属書)
物品との間に存在するI1、I2に依存している場合、選択された項目(附属書)は、物品がI2(主部材)から選択する必要がある場合、I1が示す、いくつかの関係「に依存」
関連する主要な概念やアクセサリー、とプットを置くための唯一の主な作品の後に付属品
それぞれの第一主部材ができるアタッチメントのセット一度バックパック01の処理は、第一判断することができる附属の組み合わせを、本体のそれぞれのためのコストのそれぞれの最大値を含みます
主部材01バックパックプロセスの各々について:
for i:主件k的所有附件
for j:价值(0 ~ n-主件价值)
01背包递推
得られた電荷は、[i]が0〜C-W] [i]は、これらの値f」の全ての最大値に対応する0〜C-Wでした
Vcに対応して設定メイン部材およびその付属品[I] +1 Vcを[I ] + 1V-C [I] +1 物品における物品の基であり、ここでCのコスト[I] + KC [I ] + KC [I] + kが商品F '[K] + W [I] F' [K] + W [I] Fの値である
「/ [K] + W [I]。すなわち、多くの戦略は、一つのバックパック01、Vcに変換主要素I II冗長であり、元の指数ポリシーである[I] +1 Vcを[I ] + 1V-C [I] 1つの項目は、項目のグループ、あなたが直接問題を解決するためにバックパックのグループ化アルゴリズムを使用することができます。
例
羅バレー1064
HDU 3449
#include<cstdio>
#include<cstring>
int dp[60][100010];
int max(int a,int b){return a>b?a:b;}
int main()
{
int n,tot,i,j,k;
while(scanf("%d%d",&n,&tot)!=EOF)
{
int p,m,w,v;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
scanf("%d%d",&p,&m);
for(j=0;j<p;j++)
dp[i][j]=-1;
for(j=p;j<=tot;j++)
dp[i][j]=dp[i-1][j-p];//继承上一层的结果,j-p是因为一定要买箱子
for(j=1;j<=m;j++)
{
scanf("%d%d",&w,&v);
for(k=tot;k>=w;k--)
{
if(dp[i][k-w]!=-1)
dp[i][k]=max(dp[i][k],dp[i][k-w]+v);//01背包部分
}
}
for(j=tot;j>=0;j--)//如果能更新上一层的状态,就更新。
dp[i][j]=max(dp[i][j],dp[i-1][j]);
}
printf("%d\n",dp[n][tot]);
}
return 0;
}