对背包的解释 请看 DD神牛2013最新的背包九讲.pdf
(01背包)例题和模板
1 5 10 1 2 3 4 5 5 4 3 2 1
14
1 #include<iostream> 2 using namespace std; 3 4 struct bone 5 { 6 int value; 7 int volume; 8 }b[1005]; 9 10 int max(int a,int b) 11 { 12 return a>b?a:b; 13 } 14 15 int main() 16 { 17 int t,n,v,i,j,f[1001]; 18 cin>>t; 19 while(t--) 20 { 21 scanf("%d%d",&n,&v); 22 for(i=0;i<n;i++) 23 scanf("%d",&b[i].value); 24 for(i=0;i<n;i++) 25 scanf("%d",&b[i].volume); 26 for(i=0;i<=v;i++) 27 f[i]=0; 28 for(i=0;i<n;i++) 29 for(j=v;j>=b[i].volume;j--) 30 f[j]=max(f[j],f[j-b[i].volume]+b[i].value); 31 cout<<f[v]<<endl; 32 } 33 return 0; 34 }
(多重背包)例题和模板
1 8 2 2 100 4 4 100 2
400
1 #include<iostream> 2 using namespace std; 3 4 int n,v,f[50001]; 5 bool make(int wi,int ci) 6 { 7 bool bk=1; 8 for(int j=v;j>=wi;--j) 9 if(f[j]<f[j-wi]+ci) 10 { 11 f[j]=f[j-wi]+ci; 12 bk=0; 13 } 14 return bk; 15 } 16 int main() 17 { 18 int t; 19 scanf("%d",&t); 20 while(t--) 21 { 22 scanf("%d%d",&v,&n); 23 24 memset (f,0,sizeof(f)); 25 for(int i=1;i<=n;++i) 26 { 27 int k,w,c; 28 scanf("%d%d%d",&w,&c,&k); 29 int t=1; 30 bool bo=0; 31 while(t<=k) 32 { 33 bo=make(t*w,t*c); 34 if(bo) break; 35 k-=t; 36 t*=2; 37 } 38 if(bo) continue; 39 if(k) make(k*w,k*c); 40 } 41 printf("%d\n",f[v]); 42 } 43 return 0; 44 }
(完全背包)
2934 12553
718831 13137761
1 #include<iostream> 2 using namespace std ; 3 4 int main() 5 { 6 int n,i,j; 7 int dp[35000]; 8 memset(dp,0,sizeof(dp)); 9 dp[0]=1; 10 11 for(i=1;i<=3;i++) 12 for(j=i;j<35000;j++) 13 dp[j]+=dp[j-i]; 14 while(scanf("%d",&n)!=EOF) 15 { 16 printf("%d\n",dp[n]); 17 } 18 return 0 ; 19 }
---------------------------------------------------------------------------------------
其他的题目 基本上都是在背包的基础之上进行了小小的改造
------------------------------------------------------------------------------------------
1 50 5 10 1 2 3 2 1 1 2 3 2 1 50 0
-45 32
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 int max(int a, int b) 8 { 9 return a>b?a:b; 10 } 11 int main() 12 { 13 int i,j,k; 14 int t,n,m; 15 int maxn; 16 int dp[2014]={0},price[2014]={0}; 17 while(scanf("%d",&n)!=EOF,n) 18 { 19 memset(price,0,sizeof(price)); 20 memset(dp,0,sizeof(dp)); 21 for(i=1;i<=n;i++) 22 { 23 cin>>price[i]; 24 } 25 cin>>m; 26 if(m<5) 27 { 28 printf("%d\n",m); 29 continue; 30 } 31 sort(price+1,price+n+1); 32 maxn=price[n]; 33 m=m-5; 34 for(i=1;i<n;i++) 35 { 36 for(j=m;j>=price[i];j--) 37 { 38 dp[j]=max(dp[j],dp[j-price[i]]+price[i]); 39 } 40 } 41 printf("%d\n",m+5-dp[m]-maxn); 42 } 43 return 0; 44 }
3 0.04 3 1 0.02 2 0.03 3 0.05 0.06 3 2 0.03 2 0.03 3 0.05 0.10 3 1 0.03 2 0.02 3 0.05
2 4 6
1 #include <stdio.h> 2 #define max(a,b) (a>b?a:b) 3 4 int main() 5 { 6 int t,num,v; 7 double sum,gl[105],f[10005]; 8 int val[105]; 9 while (scanf("%d",&t)!=EOF) 10 { 11 while (t--) 12 { 13 v = 0; 14 scanf("%lf%d",&sum,&num); 15 for(int i = 0;i < num; i++) 16 { 17 scanf("%d%lf",&val[i],&gl[i]); 18 v += val[i]; 19 } 20 f[0] = 1.0; 21 for(i=1;i<=v;i++) 22 f[i] = 0.0; 23 for(i = 0;i<num;i++) 24 { 25 for (int j=v;j>=val[i];j--) 26 { 27 f[j]=max(f[j],f[j-val[i]]*(1-gl[i])); 28 } 29 } 30 for(i=v;i>=0;i--) 31 { 32 if(f[i]>=(1-sum)) 33 { 34 printf("%d\n",i); 35 break; 36 } 37 } 38 } 39 } 40 return 0; 41 }
10 3 4 0.1 4 0.2 5 0.3 0 0
44.0%
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #define V 11111 5 #define N 1111 6 #define MAX(x,y) ((x)>(y)?(x):(y)) 7 using namespace std; 8 9 double dp[V]; 10 int c[N]; //每所学校花的钱 11 double w[N]; //概率 12 13 int main() 14 { 15 int n,v,i,j; 16 while(~scanf("%d%d",&v,&n)) 17 { 18 if(v==0&&n==0)break; 19 for(i=0;i<n;i++) 20 { 21 scanf("%d%lf",&c[i],&w[i]); 22 } 23 memset(dp,0,sizeof(double)*(v+1)); //double型的初始化 24 for(i=0;i<n;i++) 25 { 26 for(j=v;j>=c[i];j--) 27 dp[j] = MAX(dp[j],w[i]+(1.0-w[i])*dp[j-c[i]]);//动态方程 28 } 29 printf("%.1lf%%\n",dp[v]*100); 30 } 31 return 0; 32 }
2 1 3
0 1
1 #include<iostream> 2 3 using namespace std ; 4 5 int main() 6 { 7 8 __int64 n,i,sum; 9 int t; 10 scanf("%d",&t); 11 while(t--) 12 { 13 scanf("%I64d",&n); 14 sum = 0 ; 15 for(i=1;(i+1)*(i+1)<=(n+1);i++) 16 { 17 if((n+1)%(i+1)==0) 18 sum++; 19 } 20 printf("%I64d\n",sum); 21 } 22 23 return 0; 24 }
3 10 110 2 1 1 30 50 10 110 2 1 1 50 30 1 6 2 10 3 20 4
The minimum amount of money in the piggy-bank is 60. The minimum amount of money in the piggy-bank is 100. This is impossible.
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define INF 0xfffffff 4 int dp[10010]; 5 int min(int x,int y) 6 { 7 return x>y?y:x; 8 } 9 int main() 10 { 11 int t,e,f,n,m,p,w,i,j; 12 scanf("%d",&t); 13 while(t--) 14 { 15 scanf("%d%d",&e,&f); 16 m=f-e; 17 for(i=1;i<=m;i++) 18 dp[i]=INF; 19 dp[0]=0; 20 scanf("%d",&n); 21 for(i=0;i<n;i++) 22 { 23 scanf("%d%d",&p,&w); 24 for(j=w;j<=m;j++) //与01背包相比倒过来 25 { 26 dp[j]=min(dp[j],dp[j-w]+p); 27 } 28 } 29 if(dp[m]==INF) 30 printf("This is impossible.\n"); 31 else 32 { 33 printf("The minimum amount of money in the piggy-bank is "); 34 printf("%d.\n",dp[m]); 35 } 36 } 37 return 0; 38 }
4 10 20
5 42 627
1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 int a[123],b[123]; 7 8 int main() 9 { 10 int i,j,k; 11 for(i=0;i<=120;i++) 12 a[i]=b[i]=1; 13 for(k=2;k<=120;k++) 14 { 15 for(j=k;j<=120;j+=k) //母函数基本模板 16 for(i=0;i+j<=120;i++) 17 a[i+j]+=b[i]; 18 for(i=0;i<=120;i++) 19 b[i]=a[i]; 20 } 21 while(scanf("%d",&i)!=EOF) 22 printf("%d\n",a[i]); 23 return 0; 24 }
(ps:此题用的是 母函数)
2 900 250
0 50
1 #include<iostream> 2 3 using namespace std ; 4 5 int main() 6 { 7 int t,i,j,k,max,n,temp; 8 scanf("%d",&t); 9 while(t--) 10 { 11 scanf("%d",&n); 12 max=0; 13 for(i=0;i<=n/350;i++) 14 for(j=0;j<=n/200;j++) 15 for(k=0;k<=n/150;k++) 16 { 17 temp=i*350+j*200+k*150; 18 if(temp<=n) 19 { 20 if(temp>max)max=temp; 21 } 22 } 23 printf("%d\n",n-max); 24 } 25 return 0 ; 26 }
(ps:此题直接暴力求解了 ⊙﹏⊙)
2 10 30 0
1 4 27
1 #include<iostream> 2 3 using namespace std ; 4 5 int num[20],dp[300]; 6 7 void init() 8 { 9 int i; 10 for(i=1;i<=17;i++) 11 num[i]=i*i; 12 } 13 14 void sum(int x) 15 { 16 int i,j; 17 for(i=1;i<=17;i++) 18 { 19 if(x>=num[i]) 20 for(j=num[i];j<=x;j++) 21 dp[j]+=dp[j-num[i]]; 22 23 } 24 cout<<dp[x]<<endl; 25 } 26 int main() 27 { 28 init(); 29 int n; 30 while(scanf("%d",&n)!=EOF&&n) 31 { 32 memset(dp,0,sizeof(dp)); 33 dp[0]=1; 34 sum(n); 35 } 36 return 0 ; 37 38 }
2 2 Yili 10 500 Mengniu 20 1000 4 Yili 10 500 Mengniu 20 1000 Guangming 1 199 Yanpai 40 10000
Mengniu Mengniu
1 #include<iostream> 2 #include<cstring> 3 4 using namespace std; 5 6 #define MaxInt 0x3f3f3f3f 7 8 9 struct milk 10 { 11 char s[105];//brand 12 int p; //price 13 double pp;//per price 14 int v;//volume 15 int d;//days 16 }m[105]; 17 18 int main() 19 { 20 int t,n,i; 21 scanf("%d",&t); 22 while(t--) 23 { 24 25 scanf("%d",&n); 26 27 m[0].v=0; 28 m[0].pp=MaxInt; 29 30 for(i=1;i<=n;i++) 31 { 32 scanf("%s%d%d",m[i].s,&m[i].p,&m[i].v); 33 if(m[i].v>=200) 34 { 35 m[i].d=m[i].v/200; 36 if(m[i].d>5)m[i].d=5; 37 m[i].pp=((double)m[i].p)/(m[i].d); 38 39 40 if(m[i].pp<m[0].pp) 41 { 42 strcpy(m[0].s,m[i].s); 43 m[0].pp=m[i].pp; 44 m[0].v=m[i].v; 45 } 46 else if(m[i].pp==m[0].pp) 47 { 48 if(m[i].v>m[0].v) 49 { 50 strcpy(m[0].s,m[i].s); 51 m[0].pp=m[i].pp; 52 m[0].v=m[i].v; 53 } 54 55 } 56 } 57 } 58 printf("%s\n",m[0].s); 59 } 60 return 0; 61 }
(原谅我 我真是太暴力了。。。。)
(这道题中说 Ignatius will never drink the milk which is produced 6 days ago or earlier 一开始我认为可以喝6天 结果wa了好几次 ╮(╯▽╰)╭ 改成5就对了)