ZOJ1366经典dp(多重背包转01背包+优化空间)

【题意】:多重背包问题

【分析】:将物品按二进制拆成01的单个物品,在按照普通的背包的做法即可,同时,也可以滚动数组优化。

易错点:用数组空间用数字定义不容易弄错,

分解是按照1,2,4,8....的顺序来的

可以写成搜索(要好好研究这个方法,比如这个:http://vjudge.net/problem/viewSource.action?id=95777),可以尝试排序优化搜索的方法

【代码】:

 1  //zoj1366类似背包的问题
 2  //争取一遍AC
 3  #include<iostream>
 4  #include<string.h>
 5  #include<stdio.h>
 6  #define maxn 13
 7  using namespace std;
 8 
 9  int k[maxn];
10  int n1[maxn];
11  int c1[maxn];
12  int c2[105];
13  int dp[110000];
14  int Cash,N1,N2;
15  void solve1(){
16      N2=0;
17      for(int i=1;i<=N1;i++){
18         int now=n1[i];
19         for(int a=1;a<=now;a=a*2){
20             if (now>=a){
21                 c2[++N2]=a*c1[i];
22                 now=now-a;
23             }
24         }
25         if (now>0){
26             c2[++N2]=now*c1[i];
27         }
28      }
29  }
30  int main(){
31      while(~scanf("%d%d",&Cash,&N1)){
32         for(int i=1;i<=N1;i++) scanf("%d%d",&n1[i],&c1[i]);
33         solve1();
34         memset(dp,0,sizeof(dp));
35         dp[0]=1;
36         for(int i=1;i<=N2;i++){
37             for(int v=Cash;v>=0;v--){
38                 if (v<c2[i]) dp[v]=dp[v];
39                 else {
40                     if (dp[v-c2[i]]) dp[v]=1;
41                 }
42 //                if (dp[v])cout<<"i"<<i<<","<<v<<endl;
43             }
44         }
45         int ans=0;
46         for(int v=0;v<=Cash;v++) if (dp[v])ans=max(ans,v);
47         cout<<ans<<endl;
48 
49      }
50      return 0;
51  }
View Code
原文地址:https://www.cnblogs.com/little-w/p/3766789.html