HDU 2844 混合背包、
题意:一个人想买手表,给你n个价值的硬币,然后给你n个价值硬币对应的个数、但是呢,这个人只知道这个手表的价格不超过m元、问他最多能买多少种价值的手表
思路:dp背包专题 但是- - 一直不知道该怎么dp 终于想通了、
PS:对于背包dp说一说自己的理解吧(虽然不知道有什么用) 一旦涉及到dp 你就要考虑dp数组里面存的是什么,另外一维数组的话你就要考虑dp[i]中,那个i代表的是什么,同理二维数组也是一样、 然后写出状态转移方程,你的状态转移方程一定要和你dp数组里面存的状态是相一致的、
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 const int qq=150; 7 int a[qq],c[qq]; 8 int dp[100005]; //dp[i]代表价值为i能用硬币的最大数量、 9 int m; 10 void wanquan(int x,int y) 11 { 12 for(int i=x*y;i<=m;++i) 13 if(dp[i-x]) 14 dp[i]=max(dp[i],dp[i-x]+y); 15 else if(i-x==0) 16 dp[i]=max(dp[i],dp[i-x]+y); 17 return; 18 } 19 void beibao(int x,int y) 20 { 21 int c=x*y; 22 for(int i=m;i>=c;--i) 23 if(dp[i-c]) 24 dp[i]=max(dp[i],dp[i-c]+y); 25 else if(i-c==0) 26 dp[i]=max(dp[i],dp[i-x]+y); 27 } 28 void f(int x,int y) 29 { 30 if(x*y>=m){ 31 wanquan(x,1); 32 return; 33 } 34 int t=1; 35 while(y>=t){ 36 beibao(x,t); 37 y=y-t; 38 t=t<<1; 39 } 40 if(y) beibao(x,y); 41 } 42 int main() 43 { 44 int n; 45 while(~scanf("%d%d",&n,&m)&&(n||m)){ 46 memset(dp,0,sizeof(dp)); 47 for(int i=0;i<n;++i) 48 scanf("%d",&a[i]); 49 for(int i=0;i<n;++i) 50 scanf("%d",&c[i]); 51 int count=0; 52 for(int i=0;i<n;++i) 53 f(a[i],c[i]); 54 int sum=0; 55 // for(int i=1;i<=m;++i) 56 // printf("%d ",dp[i]); 57 for(int i=1;i<=m;++i) //dp[i]不为0也就是说能用所拥有的硬币组成价值i 58 if(dp[i]) ++sum; 59 printf("%d\n",sum); 60 } 61 return 0; 62 }
去杭州前把这道题A了 没来得及记录下、 今天补上