Description
T has being in love with Q since several years ago.Although it is really hard to maintain a long distance relationship(T and Q are not studying in the same university),T endeavors to impress and please Q every time they have a date.And as the winter holiday is approaching,T is racking his brain to make their date interesting and funny.Because Q is crazy about ice cream,T is planning to make a big ice cream which consists of different kind of small ball of ice cream.As T is a romantic and considerate boy,he wants to make Q happy and make sure the big ice cream won't contain too much calories. T finds N kind of small ball of ice cream with calories information of them.Since T knows Q immensely,he knows that if the ith kind small ball of ice cream is added to the big ice cream,Q's happy point will increase pi.
Knowing the ith kind of small ball of ice cream has ci units of calories and pi happy points,T finds it difficult to choose certain kinds of small ball of ice cream to make the big ice cream which has no more than M unit calories and can make Q as happy as possible(having the maximum happy points).Can you help T?
Input
The first line of the input contains two integers M(1<=M<=1000) and N(1<=N<=20).And there will be N lines follow.Each of them involves the information of the ith kind small ball of ice cream,Ci(the calories the ith kind of small ball of ice cream contains) and Pi(the happy point the ith kind of small ball of ice cream contains).
Output
Just output the maximum happy point the big ice cream could have.
Sample Input
100 3 95 120 30 30 10 10
Sample Output
120
題意就是說男主要做冰淇淋給女友,自己有很多類型的冰淇淋球,要用這些冰淇淋球去做一個大冰淇淋。每種冰淇淋球只能用一次且每種冰淇淋球都有一個熱量和半徑。
用戶輸入一個熱量上限一個數量n,還有n個冰淇淋球的數值,你要在保證熱量不超熱量上限的前提下讓半徑之和最大。
可謂是赤裸裸的一道最基本的揹包問題。
我是用一維01揹包的寫法做的,用一維來寫在保證時間複雜度不變的前提下節約了一維的空間,何樂而不爲呢。
#include<stdio.h>
#include<memory.h>
const int MAXV=1010;
const int MAXN=25;
int dp[MAXV];
int v[MAXN];
int p[MAXN];
int main()
{
int bv,n;
while(scanf("%d%d",&bv,&n)!=EOF)
{
memset(dp,0,(bv+1)*sizeof(int));
for(int i=1;i<=n;i++)
scanf("%d%d",&v[i],&p[i]);
for(int i=1;i<=n;i++)
for(int j=bv;j>=v[i];j--)
{
if(dp[j]<dp[j-v[i]]+p[i])
dp[j]=dp[j-v[i]]+p[i];
}
printf("%d\n",dp[bv]);
}
return 0;
}
揹包是一種dp問題,最重要的就是思考如何表示那個狀態轉移。
一維最大值01揹包可以解釋爲:dp[j]=max(dp[j],dp[j-c[i]]+v[i])
i是當前放了前i個物品,j是當前揹包容量,dp[j]是當前容量下的最大價值,c[i]是物品的代價即重量或者體積等,v[i]是物品的價值
這個方程的意思就是當前容量的揹包的價值的最大值要麼是還沒放下第i個物體時的價值,要麼是清掉某些東西直到能放下第i個物品後的最大值
而初始條件是所有dp全部爲0,用這道方程從揹包容量最大放第一個物品開始循環求解即可