DP-01背包问题例题
输入处理有点恶心人,不过处理完后就是简单的DP了
从头开始dp[i]表示从0开始到i的最优结果,最后从都边里dp数组,求得最大的报销额。
对于每个i都要从头维护最优结果。(二刷感觉仍不得dp精髓,,,,)
HDU-1864最大报销额
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <queue> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cmath> 6 #include <cstring> 7 #include <queue> 8 #include <map> 9 #include <vector> 10 #define INF 0x3f3f3f3f 11 #define FRE() freopen("in.txt","r",stdin) 12 13 using namespace std; 14 typedef long long ll; 15 const int maxn = 500; 16 double dp[maxn]; 17 double money,a[maxn]; 18 19 bool judge(char op) 20 { 21 if(op=='A'||op=='B'||op=='C') 22 return true; 23 return false; 24 } 25 26 27 void init(int n,int& index) 28 { 29 char op,ch; 30 while(n--) 31 { 32 int x,ok = 1; 33 double tmp,sumA = 0,sumB = 0,sumC = 0; 34 cin>>x; 35 for(int i = 0; i<x; i++) 36 { 37 cin>>ch>>op>>tmp; 38 if(judge(ch)) 39 { 40 if(ch=='A')sumA += tmp; 41 if(ch=='B')sumB += tmp; 42 if(ch=='C')sumC += tmp; 43 } 44 else 45 ok = 0; 46 } 47 if(ok && (sumA<=600.0 && sumB<=600.0 && sumC<=600.0 && (sumA+sumB+sumC) <=1000.0)) 48 a[index++] = (sumA+sumB+sumC)*100.0; 49 } 50 return; 51 } 52 53 54 int main() 55 { 56 int n,index = 0,in; 57 while(cin>>money>>n) 58 { 59 if(n==0)break; 60 index = 0; 61 memset(a,0,sizeof(a)); 62 init(n,index); 63 // for(int i = 0; i<index; i++) 64 // { 65 // cout<<a[i]<<" "; 66 // } 67 // cout<<endl<<endl; 68 memset(dp,0,sizeof(dp)); 69 in = 1; 70 for(int i = 0; i<index; i++)//枚举每一个可以报销的票 71 { 72 for(int j = 0; j<=i; j++) 73 { 74 if(dp[j]+a[i] <= money*100.0) 75 { 76 dp[i] = max(dp[i],dp[j]+a[i]);//每一个票的位置上对应一个dp维护该位置上的最大报销额度 77 } 78 } 79 } 80 double ans = 0; 81 for(int i = 0; i<index; i++) 82 { 83 ans = max(ans,dp[i]); 84 } 85 printf("%.2f\n",ans/100.0); 86 } 87 return 0; 88 }
HDU-2602 Bone Collector
01背包问题的板子问题
做这个题的时候尝试了紫书上讲的滚动数组;
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 const int maxn = 1005; 7 int N,V; 8 int wet[maxn],val[maxn]; 9 int dp[maxn]; 10 11 int main() 12 { 13 //freopen("in.txt","r",stdin); 14 int T; 15 scanf("%d",&T); 16 while(T--) 17 { 18 memset(wet, 0, sizeof(wet)); 19 memset(val, 0, sizeof(val)); 20 memset(dp, 0, sizeof(dp)); 21 scanf("%d%d",&N,&V); 22 for(int i = 0; i < N; i++) 23 scanf("%d",&val[i]); 24 for(int i = 0; i < N; i++) 25 scanf("%d",&wet[i]); 26 for(int i = 0; i < N; i++)//枚举每一块骨头 27 { 28 for(int j = V; j >= 0; j--)//枚举背包体积区间的每一个大小 29 { 30 if(j >= wet[i])//如果背包体积大于骨头的体积 31 dp[j] = max(dp[j], dp[j - wet[i]] + val[i]);//更新该体积所能装下的最大的价值 32 } 33 } 34 printf("%d\n",dp[V]); 35 } 36 return 0; 37 }