http://www.cnblogs.com/rainydays/archive/2013/03/08/2950258.html
http://www.cnblogs.com/ziyi--caolu/p/3216827.html
第一种:
邻接+统计数量
#include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <cctype> #include <vector> #include <iterator> #include <set> #include <map> #include <sstream> using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) #define pf printf #define sf scanf #define spf sprintf #define pb push_back #define debug printf("! ") #define MAXN 1010 #define MAX(a,b) a>b?a:b #define blank pf(" ") #define LL long long #define ALL(x) x.begin(),x.end() #define INS(x) inserter(x,x.begin()) #define pqueue priority_queue #define INF 0x3f3f3f3f int cash,n,sum; int c[15],w[15],used[100005]; bool f[100005]; void mubag() { int i,j; mem(f,false); f[0] = true; //debug; for(i=0;i<n;i++) { mem(used,0); for(j = w[i];j<=cash;j++) { if(f[j-w[i]] && !f[j] && used[j-w[i]]<c[i]) { f[j] = true; used[j] = used[j-w[i]]+1; //pf("f%d cnt%d ",j,used[j]); } } } } int main() { int i,j; while(~sf("%d%d",&cash,&n)) { for(i=0;i<n;i++) { sf("%d%d",&c[i],&w[i]); } mubag(); for(i=cash;i>=0;i--) { if(f[i]) { pf("%d ",i); break; } } } return 0; }
第二种:
二进制拆分+01背包
value = weight
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; int dp[110000],t[30000],s[2000][2]; int main() { int cash,n; while(scanf("%d%d",&cash,&n)>0) { int cnt=0; //memset(t,0,sizeof(t)); for(int i=1;i<=n;i++) { scanf("%d%d",&s[i][0],&s[i][1]); int k=1; if(s[i][0]==0||s[i][1]==0) continue; while(s[i][0]-k>0) { t[cnt++]=k*s[i][1]; s[i][0]-=k; k*=2; } t[cnt++]=s[i][0]*s[i][1]; } memset(dp,0,sizeof(dp)); for(int i=0;i<cnt;i++) { for(int j=cash;j>=t[i];j--) if(dp[j]<dp[j-t[i]]+t[i]) dp[j]=dp[j-t[i]]+t[i]; } printf("%d ",dp[cash]); } return 0; }
第三种:
完全背包+统计数量
value = weight
基本和第一种一样,速度也一样,更清晰一点
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; int dp[110000],num[100100],s[2000][2]; int main() { int cash,n; while(scanf("%d%d",&cash,&n)>0) { int cnt=0; for(int i=1;i<=n;i++) { scanf("%d%d",&s[i][0],&s[i][1]); } memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) { memset(num,0,sizeof(num)); for(int j=s[i][1];j<=cash;j++) if(dp[j]<dp[j-s[i][1]]+s[i][1]&&num[j-s[i][1]]<s[i][0]) { dp[j]=dp[j-s[i][1]]+s[i][1]; num[j]=num[j-s[i][1]]+1; } } printf("%d ",dp[cash]); } return 0; }