今天重新学习了多重背包,为选拔赛做准备。
这道题学习了大神键盘上的舞者的模板,感谢~
本题就是简单的多重背包,先判断将该硬币化为完全背包还是01背包处理,01背包利用二进制化简。
题目求的是一共能表示多少种price,这里答案用dp[ i ] == i 判断,原因如下:
这道题全部初始化为零,也就是不装满求最大,硬币代表的价值为背包容量,同时也是背包里的值。当dp[ i ]即最大容量为i时,装i是最大的,而当dp[ i ]的值不等于i,则说明没装满,也就是说会有 dp[ dp[ i ] ] = dp[ i ],所以每一种price都会在dp[ price ]中出现,故这样求结果。
#include<iostream> #include<stdio.h> #include<math.h> #include<string.h> #include<vector> #include<list> #include<algorithm> using namespace std; int n,m; int v[110]; int t[110]; int dp[100010]; void MP(int value,int space,int num); int main(){ scanf("%d%d",&n,&m); while(n||m){ for(int i=0;i<n;i++){ scanf("%d",&v[i]); } for(int i=0;i<n;i++){ scanf("%d",&t[i]); } memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++){ MP(v[i],v[i],t[i]); } int sum = 0; for(int i=1;i<=m;i++){ if(i==dp[i]) sum++; } printf("%d\n",sum); scanf("%d%d",&n,&m); } return 0; } //完全背包 void CP(int value,int space){ for(int i=value;i<=m;i++){ dp[i] = max(dp[i],dp[i-value] + space); } } //01背包 void ZOP(int value,int space){ for(int i=m;i>=value;i--){ dp[i] = max(dp[i],dp[i-value] + space); } } //多重背包判断转化 void MP(int value,int space,int num){ if(num*value>=m){//当总价值超过背包容量 CP(value,space); } else{//二进制转化 int k=1; while(k<=num){ ZOP(value*k,space*k); num-=k; k*=2; } ZOP(value*num,space*num); } }