1. 程式人生 > >二維揹包 - 潛水員(Codevs 5056)

二維揹包 - 潛水員(Codevs 5056)

潛水員

描述
潛水員為了潛水要使用特殊裝備。他有一個帶兩種氣體的氣缸:一個為氮氣,一個為氧氣。讓潛水員下潛的深度需要各種數量的氧和氮。潛水員有一定數量的氣缸。每個氣缸都有重量和氣體容量。潛水員為了完成他的工作需要特定的氧和氮。他完成工作所需氣缸的總重最低限度是多少?
例如:潛水員有5個氣缸。每行有三個數字為:氧、氮的量(升)和氣缸的重量:
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119
如果潛水員需要5升的氧和60升的氮則總重的最小值為249(1,2或4,5號氣缸)。
你的任務就是計算潛水員為了完成他的工作需要的氣缸的重量的最低值。

輸入
第一行有2個整數m,n(1<=m<=21,1<=n<=79)。它們表示氧、氮各自需要的量。
第二行為整數k(1<=k<=1000)表示氣缸的個數。
此後的k行,每行包括ai,bi,ci(1<=ai<=21,1<=bi<=79,1<=ci<=800)3整數
這些各自是:第i個氣缸裡的氧和氮的容量及氣缸重量。

輸出
僅一行,包含一個整數,為潛水員完成工作所需氣缸的重量總和的最低值。

樣例輸入
5 60
5
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119
樣例輸出
249
提示
提示 1<=m<=21,1<=n<=79 1<=k<=1000 1<=ai<=21,1<=bi<=79,1<=ci<=800


Analysis

和我想的差不多,發現這個東西N2和O2其實是沒有上限的,也就是說如果我們用揹包的思想來想,這個包是可以無限大的,那麼我們常見套路從i-1推i,顯然不可做
那就轉變一下,每次都從i去推i+1,只要當前已有的N2和O2數量加上現在這個氣缸的貢獻是大於我們需要的m和n,我們就直接把這次的貢獻算在f[m][n]上
然後就完啦

Code

#include<bits/stdc++.h>
#define N 2000
using namespace std;
int n,m,k;
int o2[N],n2[N],f[N][N],c[N];
int main(){
	scanf("%d%d%d",&m,&n,&k);
	int i,j,p;
	for(i=1;i<=k;++i) scanf("%d%d%d",&o2[i],&n2[i],&c[i]);
	memset(f,127/3,sizeof(f));
	f[0][0]=0;
	for(i=1;i<=k;
++i){ for(j=m;j>=0;--j)//從前面的狀態往後轉移 for(p=n;p>=0;--p) { int jj=j+o2[i]; int pp=p+n2[i]; if(jj>m) jj=m; if(pp>n) pp=n; f[jj][pp]=min(f[j][p]+c[i],f[jj][pp]); } } printf("%d",f[m][n]); return 0; }