http://acm.hdu.edu.cn/showproblem.php?pid=2191
New~ 欢迎“热爱编程”的高考少年——报考杭州电子科技大学计算机学院 关于2015年杭电ACM暑期集训队的选拔 |
悼念512汶川大地震遇难同胞——珍惜现在,感恩生活Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description 急!灾区的食物依然短缺! 后记: Input 输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。 Output 对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。 Sample Input 1 Sample Output 400 Author lcy Source 2008-06-18《 ACM程序设计》期末考试——四川加油!中国加油! Recommend lcy | We have carefully selected several similar problems for you: 1114 2602 2159 1171 1059 |
1 #include<stdio.h> 2 #include<string.h> 3 int dp[101];//dp[j]表示钱为j时能买的最大重量 4 struct Node 5 { 6 int p;//价格 7 int w;//重量 8 int c;//数量 9 }s[102]; 10 int main() 11 { 12 int t,N,m; 13 int i,j,k,temp; 14 scanf("%d",&t); 15 while(t--) 16 { 17 memset(dp,0,sizeof(dp)); 18 scanf("%d%d",&N,&m); 19 for(i=1;i<=m;i++) 20 scanf("%d%d%d",&s[i].p,&s[i].w,&s[i].c); 21 for(j=0;j<s[1].p;j++) 22 dp[j] = 0; 23 for(;j<=N;j++) 24 { 25 temp = j/s[1].p; 26 if(temp <= s[1].c) 27 dp[j] = temp * s[1].w; 28 else 29 dp[j] = s[1].c * s[1].w; 30 } 31 32 for(i=2;i<=m;i++)//米的种类 33 { 34 for(j=N;j>=s[i].p;j--)//钱的数量 35 { 36 for(k = 0;k<=s[i].c;k++)//米的代数 37 { 38 temp = k * s[i].p; 39 if(temp <= j ) 40 { 41 if(dp[j-temp]+k*s[i].w > dp[j]) 42 dp[j] = dp[j-temp]+k*s[i].w; 43 } 44 else 45 break; 46 } 47 } 48 } 49 printf("%d\n",dp[N]); 50 } 51 return 0; 52 }
二进制拆分:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 const int N=110; 5 using namespace std; 6 int n,m; 7 8 struct Rice{ 9 int price; 10 int weight; 11 int number; 12 }rice[N]; 13 int dp[N]; 14 //完全背包 15 void CompletePack(int cost,int weight){ 16 for(int i=cost;i<=n;i++){ 17 dp[i]=max(dp[i],dp[i-cost]+weight); 18 } 19 } 20 //01背包 21 void ZeroOnePack(int cost,int weight){ 22 for(int i=n;i-cost>=0;i--){ 23 dp[i]=max(dp[i],dp[i-cost]+weight); 24 } 25 } 26 27 //多重背包 28 void MultiplePack(int cost,int weight,int number){ 29 //如果大于等于金额,就按完全背包处理(此时相当于不限定袋数) 30 if(cost*number>=n){ 31 CompletePack(cost,weight); 32 return ; 33 } 34 int k=1; 35 while(k<number){ 36 ZeroOnePack(k*cost,k*weight); 37 number-=k; 38 k*=2; 39 } 40 ZeroOnePack(number*cost,number*weight); 41 } 42 43 int main(){ 44 int _case; 45 scanf("%d",&_case); 46 while(_case--){ 47 scanf("%d%d",&n,&m); 48 memset(dp,0,sizeof(dp)); 49 for(int i=0;i<m;i++){ 50 scanf("%d%d%d",&rice[i].price,&rice[i].weight,&rice[i].number); 51 } 52 for(int i=0;i<m;i++){ 53 MultiplePack(rice[i].price,rice[i].weight,rice[i].number); 54 } 55 printf("%d\n",dp[n]); 56 } 57 return 0; 58 }