c++背包問題
動態規划和貪心中的五個背包問題,收集並整理出來放在這里。
0/1背包問題
0/1背包問題是一道動規的題,其題目意思就是每樣物品只能取一個。二維表格中概括來說是上面位置的數&&上面的位置減物品質量這個數值后這個位子上的數加物品的價值比較哪個大,這里為了方便都轉換為一維數組來做。(一樣的)
#include <iostream>
using namespace std;
int dp[100];
int main()
{<!-- -->
int n;
int m;
cin>>m>>n;
int w[100];
int c[100];
for (int i=1;i<=n;i++)
{<!-- -->
cin>>w[i]>>c[i];
}
for (int i=1;i<=n;i++)
{<!-- -->
for (int j=1;j<=m;j++)
{<!-- -->
if (j>=w[i])
{<!-- -->
dp[j]=max(dp[j],dp[j-w[i]]+c[i]);
}
}
}
cout<<dp[m];
return 0;
}
其中w[]是體積,c[]是價值。
完全背包問題
完全,也就是物品可以取無限件。沒什么差別,只是表格橫向不一樣(從小到大,從當前體積開始)
#include <bits/stdc++.h>
using namespace std;
int dp[1090];
int main()
{<!-- -->
int n;
int v;
cin>>n>>v;
int n1[1000];
int v1[1000];
for (int i=1;i<=n;i++)
{<!-- -->
cin>>n1[i]>>v1[i];
}
for (int i=1;i<=n;i++)
{<!-- -->
for (int j=n1[i];j<=v;j++)
{<!-- -->
dp[j]=max(dp[j],dp[j-n1[i]]+v1[i]);
}
}
cout<<dp[v]<<endl;
return 0;
}
n1[]是體積,v1[]是價值。
多重背包問題
無非是0/1背包多了一個數量控制罷了。
#include<iostream>
using namespace std;
int dp[1000];
int main()
{<!-- -->
int N,V;
cin>>N>>V;
int v[1000],w[1000],s[1000];
for (int i=1;i<=N;i++)
{<!-- -->
cin>>w[i]>>v[i]>>s[i];
}
for (int i=1;i<=N;i++)//商品種類的數量
{<!-- -->
for (int j=V;j>=w[i];j--)//背包空間
{<!-- -->
for (int k=1;k<=s[i]&&k*s[i]<=j;k++)//數量限制
{<!-- -->
dp[j]=max(dp[j],dp[j-w[i]*k]+v[i]*k);
}
}
}
cout<<dp[V]<<endl;
return 0;
}
w[]是體積,v[]是價值,s[]是數量。
混合背包問題
三種混起來而已,我甭說了吧
#include <iostream>
using namespace std;
int dp[1000];
int main()
{<!-- -->
int n,V;
cin>>V>>n;
int w[1000],v[1000],c[1000];
for (int i=1;i<=n;i++)
{<!-- -->
cin>>w[i]>>v[i]>>c[i];
}
for (int i=1;i<=n;i++)
{<!-- -->
if (c[i]==1)
{<!-- -->
for (int j=V;j>=w[i];j--)
{<!-- -->
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
}
else if (c[i]==0)
{<!-- -->
for (int j=w[i];j<=V;j++)
{<!-- -->
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
}
else if (c[i]>1)
{<!-- -->
for (int j=V;j>=w[i];j--)//背包空間
{<!-- -->
for (int k=1;k<=c[i]&&k*w[i]<=j;k++)//數量限制
{<!-- -->
dp[j]=max(dp[j],dp[j-w[i]*k]+v[i]*k);
}
}
}
}
cout<<dp[V]<<endl;
return 0;
}
貪心背包問題
前四種都是動規,這種是貪心哦。又叫小數背包問題。
#include <iostream>
//#include <algorithm>
#include <iomanip>
using namespace std;
int m,n;
struct node
{<!-- -->
int v,w;
double k;
}a[1000];
bool cmp(node x,node y)
{<!-- -->
return x.k>y.k;
}
int main()
{<!-- -->
double sum=0;
cin>>m>>n;
for (int i=0;i<n;i++)
{<!-- -->
cin>>a[i].v>>a[i].w;
a[i].k=a[i].v*1.0/a[i].w;
}
// sort (a,a+n,cmp);
for (int i=0;i<n-1;i++)
{<!-- -->
for (int j=i+1;j<n;j++)
{<!-- -->
if (a[i].k<a[j].k)
{<!-- -->
swap(a[i],a[j]);
}
}
}
for (int i=0;i<n;i++)
{<!-- -->
if (m>=a[i].w)
{<!-- -->
sum+=a[i].v;
m-=a[i].w;
}
else
{<!-- -->
sum+=a[i].k*m;
break;
}
}
cout<<fixed<<setprecision(2)<<sum<<endl;
return 0;
}
結構體中,v是價值,w是體積,k是性價比。
這五種背包,腦子和手都學廢了吧(●’◡’●)。 點個贊再走唄~~~