poj 1276 多重背包+二进制解法

来源:互联网 发布:淘宝刷流量有用么 编辑:程序博客网 时间:2024/04/30 06:48

这题用来实验《背包九讲》里的转二进制01背包解法,先是普通解法O(VN):

#include<iostream>  #include <string>   #include<vector>  #include<algorithm>  #include<set>  #include<fstream>#include<cmath>  #include<queue>using namespace std;  #define lch(i) ((i)<<1)  #define rch(i) ((i)<<1|1)  #define sqr(i) ((i)*(i))  #define pii pair<int,int>  #define mp make_pair  #define FOR(i,b,e) for(int i=b;i<=e;i++)  #define FORE(i,b,e) for(int i=b;i>=e;i--)  #define ms(a)   memset(a,0,sizeof(a))  const int maxnum =100005;const int INF = 25000005;int tol,n,m;int dp[maxnum];struct node{int v,num;node(){}node(int v1,int num1):v(v1),num(num1){}}tp[maxnum];int main()  {  //fstream fin("G:/1.txt");//while(fin>>m>>n){while(scanf("%d%d",&m,&n)!=EOF){ms(dp);ms(tp);FOR(i,1,n){scanf("%d%d",&tp[i].num,&tp[i].v);//fin>>tp[i].num>>tp[i].v;}int num[maxnum];dp[0]=1;FOR(i,1,n){ms(num);FOR(j,tp[i].v,m){if(!dp[j]&&dp[j-tp[i].v]&&num[j-tp[i].v]<tp[i].num){dp[j]=1;num[j]=num[j-tp[i].v]+1;}}}FORE(i,m,0){if(dp[i]){printf("%d\n",i);break;}}}return 0;}


二进制解法,复杂度比上面略高,O(VΣlogMi)但适用性广一点:

#include<iostream>  #include <string>   #include<vector>  #include<algorithm>  #include<set>  #include<fstream>#include<cmath>  #include<queue>using namespace std;  #define lch(i) ((i)<<1)  #define rch(i) ((i)<<1|1)  #define sqr(i) ((i)*(i))  #define pii pair<int,int>  #define mp make_pair  #define FOR(i,b,e) for(int i=b;i<=e;i++)  #define FORE(i,b,e) for(int i=b;i>=e;i--)  #define ms(a)   memset(a,0,sizeof(a))  const int maxnum =100005;const int INF = 25000005;int tol,n,m,newn;int dp[maxnum];struct node{int v,num;node(){}node(int v1,int num1):v(v1),num(num1){}}tp[maxnum];int ntp[maxnum*14];int main()    {       // fstream fin("G:/1.txt");      //while(fin>>m>>n){      while(scanf("%d%d",&m,&n)!=EOF){  ms(dp);ms(tp);ms(ntp);newn=0;        FOR(i,1,n){              scanf("%d%d",&tp[i].num,&tp[i].v);  //fin>>tp[i].num>>tp[i].v;  int k=log(tp[i].num+1.0)/log(2.0);FOR(j,0,k-1){ntp[++newn] = tp[i].v*pow((float)2,(float)j);}if(tp[i].num+1-pow((float)2,(float)k))ntp[++newn] = (tp[i].num+1-pow((float)2,(float)k))*tp[i].v;                   }  dp[0]=1;FOR(i,1,newn){FORE(j,m,1){if(j<ntp[i])continue;dp[j]=max(dp[j],dp[j-ntp[i]]);}}        FORE(i,m,0){              if(dp[i]){                  printf("%d\n",i);break;}          }      }      return 0;  }  



0 0