1 8 2 2 100 4 4 100 2
400
基本算法
有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。复杂度是O(V*Σn[i])。
将这个 多重背包问题转化为 完全背包问题,也就是每个物品都有无限个,但是在循环过程中用一个数组记录:某种硬币i使用的次数,如果使用次数超过c[i],则停止循环。恩,大意如此,时间复杂度就是O(n*m),终于AC。
O(V*Σn[i])算法:
#include<iostream>//c++ #include<cmath>//数学公式 #include<cstdlib>//malloc #include<cstring> #include<string> #include<cstdio>//输入输出 #include<algorithm>//快排 #include<queue>//队列 #include<functional>//优先队列 #include<stack>//栈 #include<vector>//容器 #include<map>//地图 if continue typedef long long ll; const int N=105; using namespace std; int label[N]; int dp[N]; int main() { // freopen("C:\\Users\\ch\\Desktop\\1.txt","r",stdin); //freopen("C:\\Users\\lenovo\\Desktop\\2.txt","w",stdout); int i,j,k; int v,n,text; int a,b,c; cin>>text; while(text--) { memset(dp,0,sizeof(dp)); cin>>v>>n; for(i=0;i<n;i++) { cin>>a>>b>>c;//a->v b->w c->n for(k=0;k<c;k++) for(j=v;j>=a;j--) dp[j]=max(dp[j],dp[j-a]+b); } cout<<dp[v]<<endl; } return 0; }
O(V*Σlog count[i])写法(二进制优化)
#include<iostream>//c++ #include<cmath>//数学公式 #include<cstdlib>//malloc #include<cstring> #include<string> #include<cstdio>//输入输出 #include<algorithm>//快排 #include<queue>//队列 #include<functional>//优先队列 #include<stack>//栈 #include<vector>//容器 #include<map>//地图 if continue typedef long long ll; const int N=105; using namespace std; int label[N]; int dp[N]; int main() { // freopen("C:\\Users\\ch\\Desktop\\1.txt","r",stdin); //freopen("C:\\Users\\lenovo\\Desktop\\2.txt","w",stdout); int i,j,k; int v,n,text; int a,b,c; cin>>text; while(text--) { memset(dp,0,sizeof(dp)); cin>>v>>n; for(i=0;i<n;i++) { cin>>a>>b>>c;//a->v b->w c->n for(k=1;k*2<1+c;k*=2)//1 2 4 8 for(j=v;j>=a*k;j--) dp[j]=max(dp[j],dp[j-k*a]+k*b); k = c + 1 - k; for(j=v;j>=a*k;j--) dp[j]=max(dp[j],dp[j-k*a]+k*b); } cout<<dp[v]<<endl; } return 0; }
#include<iostream>//c++ #include<cmath>//数学公式 #include<cstdlib>//malloc #include<cstring> #include<string> #include<cstdio>//输入输出 #include<algorithm>//快排 #include<queue>//队列 #include<functional>//优先队列 #include<stack>//栈 #include<vector>//容器 #include<map>//地图 if continue typedef long long ll; const int N=105; using namespace std; int label[N]; int dp[N]; typedef struct { int a,b,c; double d; }G;G g[105]; bool cmp(G a,G b) { return a.d>b.d; } int main() { // freopen("C:\\Users\\ch\\Desktop\\1.txt","r",stdin); <span style="white-space:pre"> </span>//freopen("C:\\Users\\lenovo\\Desktop\\2.txt","w",stdout); <span style="white-space:pre"> </span>int i,j,k; <span style="white-space:pre"> </span>int v,n,text; int a,b,c; cin>>text; while(text--) { memset(dp,0,sizeof(dp)); cin>>v>>n; for(i=0;i<n;i++) cin>>g[i].a>>g[i].b>>g[i].c,g[i].d=1.0*g[i].b/g[i].a;//a->v b->w c->n sort(g,g+n,cmp);//排 序 int ans=0; for(i=0;i<n;i++) { memset(label,0,sizeof(label)); for(j=g[i].a;j<=v;j++) if(label[j-g[i].a]<g[i].c) { if(dp[j]<dp[j-g[i].a]+g[i].b) { dp[j]=dp[j-g[i].a]+g[i].b; label[j]=label[j-g[i].a]+1; ans=max(dp[j],ans); } } } cout<<ans<<endl; } return 0; }
例题:http://poj.org/problem?id=1742
AC代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; bool can_pay[100005]; int use_ai[100005]; int Ai[105], Ci[105]; int n, m, ans; int coins(); int main() { int i; while(scanf("%d%d", &n, &m), n || m) { memset(can_pay, false, sizeof(can_pay)); can_pay[0] = true; for(i = 0; i < n; ++i) scanf("%d", &Ai[i]); for(i = 0; i < n; ++i) scanf("%d", &Ci[i]); coins(); } return 0; } int coins() { int i, j; ans = 0; for(i = 0; i < n; ++i) { memset(use_ai, 0, sizeof(use_ai)); for(j = Ai[i]; j <= m; ++j) { if(!can_pay[j] && can_pay[j - Ai[i]] && use_ai[j - Ai[i]] < Ci[i]) { can_pay[j] = true; use_ai[j] = use_ai[j - Ai[i]] + 1; ++ans; } } } printf("%d\n", ans); return 0; }