揹包專題 01揹包

2021-06-16 13:03:14 字數 3288 閱讀 2383

暑假集訓開始了,按照隊裡的分配,我是弄dp的,嘛,於是我又一次的開始了從01揹包開始學習,昨天將杭電的幾道01揹包重新做了一遍,下面講講我自己對於01揹包的理解。

首先01揹包題目的雛形是

有n件物品和乙個容量為v的揹包。第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使價值總和最大。

從這個題目中可以看出,01揹包的特點就是:每種物品僅有一件,可以選擇放或不放。

其狀態轉移方程是:

f[i][v]=max

對於這方方程其實並不難理解,方程之中,現在需要放置的是第i件物品,這件物品的體積是c[i],價值是w[i],因此f[i-1][v]代表的就是不將這件物品放入揹包,而f[i-1][v-c[i]]+w[i]則是代表將第i件放入揹包之後的總價值,比較兩者的價值,得出最大的價值存入現在的揹包之中。

理解了這個方程後,將方程代入實際題目的應用之中,可得

for(i = 1; i<=n; i++)

}

理解了01揹包之後,下面就來看看實際的題目

hdu2546:飯卡

很經典的一道01揹包題,要注意的是這裡只要剩餘的錢不低於5元,就可以購買任何一件物品,所以5在這道題中是很特許的,再使用01揹包之前,我們首先要在現在所擁有的餘額中保留5元,用這五元去購買最貴的物品,而剩下的錢就是揹包的總容量,可以隨意使用,因此可得**

#include #include using namespace std;

int cmp(int a,int b)

}printf("%d\n",m+5-dp[m]-max);

}return 0;

}

hdu1171:big event in hdu

這道題咋看有點複雜,其實也只是換了一種思維,因為題目要求要盡量平均分配,所以我們可以先將總價值sum求出,然後得出其分配的平均值為sum/2,要注意這個答案可能為小數,但是又因為sum是整數,所以最後得出的sum/2是要小於等於實際的值。將這個結果進行01,揹包,可以得出其中乙個宿舍所得的最大價值,而另乙個宿舍的最大價值也可以相應的得到,而前者必定小於等於後者。

#include #include #include using namespace std;

int val[5005];

int dp[255555];

int main()

}printf("%d %d\n",sum-dp[sum/2],dp[sum/2]);

}return 0;

}

hdu2602:bone collector

經典的01揹包題,給出了石頭的數量與揹包的容量,然後分別給出每個石頭的容量與價值,要求最優解,經過前面的練手,這道題已經是很簡單了,可以說是01揹包果題。

#include #include #include using namespace std;

struct node

node[1005];

int main()

printf("%d\n",dp[m]);

}return 0;

}

hdu2639:bone collector ii(01揹包第k優解)

解決了上面那倒題目之後,這道題跟上面的題目有些不同,因為這裡要求的是第k優解

#include #include #include using namespace std;

struct node

node[1005];

int main()

,a[31],b[31];

scanf("%d%d%d",&n,&v,&k);

for(i = 0; i=node[i].val; j--)

int x,y,z;

x = y = z = 1;

a[d] = b[d] = -1;

while(z<=k && (x<=k || y<=k))//迴圈找出前k個的最優解

else

if(dp[j][z]!=dp[j][z-1])

z++;}}

}printf("%d\n",dp[v][k]);

}return 0;

}

hdu2955:robberies

這道題有點特別,咋看之下其狀態轉移方程似乎有些不同,但事實上遠離是相通的,要注意其精度

#include #include using namespace std;

struct bank

bank[10005];

int main()

}for(i = sum; i>=0; i--)}}

return 0;

}

hdu3466:proud merchants

這道題由於規定了手上的前低於q時就不能購買該樣東西,所以要先將商品按q-p排序,剩下的就是簡單的01揹包了

#include #include #include using namespace std;

struct node

a[555];

int cmp(node x,node y)//按q-p排序,保證差額最小為最優

}printf("%d\n",dp[m]);

}return 0;

}

hdu1864:最大報銷額

題目中藥注意的有幾樣,首先每張發票中單件物品**不能超過600,其次發票總額不能超過1000,而且發票上的物品必須是abc三類,將滿足以上條件的發票存入陣列之中,就是裸01揹包

#include #include #include using namespace std;

int dp[3000050];//由於每張發票不超過1000,最多30張,擴大100倍數後開這麼大即可

int main()

printf("%.2lf\n",dp[sum]/100.0);

}return 0;

}

恩,01揹包的專題就到這裡了,第一次說演算法,說得不咋樣,語言表達能力有限,各位看客求寬容啊!!!

揹包九講專題 01揹包

樸素2維無優化寫法 includeusing namespace std const int maxn 1e3 5 int dp maxn maxn v maxn w maxn intmain printf d n dp n m view code 優化1維寫法 關於優化是怎麼來的?首先為什麼第二個...

揹包 01揹包

01揹包 有n種物品與承重為m的揹包。每種物品只有一件,每個物品都有對應的重量weight i 與價值value i 求解如何裝包使得價值最大。dp i,v 表示前i個物體 包括第i個 面對容量為v的揹包的最大價值,c i 代表物體i的重量,w i 代表物體i的價值 如果第i個物體不放入揹包,則揹包...

揹包 01揹包,完全揹包,多重揹包

哈哈 01揹包 f i v max 完全揹包 f i v max 多重揹包 f i v max include include include include include define maxn 1000 using namespace std int n,cap int w maxn 重量 花...