这段时间要开始刷dp了,记录点点滴滴。21:33:51
一.基础dp:
1.hdu.2602.Bone Collector.
这道是基础的01背包。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAXN=1000+10; 5 int w[MAXN]; 6 int v[MAXN]; 7 int dp[MAXN]; 8 int main() 9 { 10 int test; 11 scanf("%d",&test); 12 while(test--) 13 { 14 int n,V; 15 scanf("%d%d",&n,&V); 16 for(int i=1;i<=n;i++) 17 scanf("%d",&w[i]); 18 for(int i=1;i<=n;i++) 19 scanf("%d",&v[i]); 20 for(int j=0;j<=V;j++) 21 dp[j]=0; 22 for(int i=1;i<=n;i++) 23 for(int j=V;j>=v[i];j--) 24 { 25 dp[j]=max(dp[j],dp[j-v[i]]+w[i]); 26 } 27 int ans=0; 28 for(int j=0;j<=V;j++) 29 if(dp[j]>ans) 30 ans=dp[j]; 31 printf("%d\n",ans); 32 } 33 return 0; 34 }
2.poj.3624.Charm Bracelet.
基础01背包,注意下标的最大值为物品数还是背包容量最大值。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAXN=3410; 5 const int MAXM=13000; 6 int w[MAXN]; 7 int cost[MAXN]; 8 int dp[MAXM]; 9 int main() 10 { 11 int n,m; 12 while(scanf("%d%d",&n,&m)!=EOF) 13 { 14 for(int i=1;i<=n;i++) 15 scanf("%d%d",&cost[i],&w[i]); 16 for(int j=0;j<=m;j++) 17 dp[j]=0; 18 for(int i=1;i<=n;i++) 19 for(int j=m;j>=cost[i];j--) 20 dp[j]=max(dp[j],dp[j-cost[i]]+w[i]); 21 int ans=0; 22 for(int i=0;i<=m;i++) 23 if(dp[i]>ans) 24 ans=dp[i]; 25 printf("%d\n",ans); 26 } 27 return 0; 28 }
3.hdu.2546.饭卡.
先预留5元去买最贵的菜,注意n==0 时结束。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=1000+5; 5 const int maxm=1000+5; 6 int a[maxn]; 7 int dp[maxm]; 8 int main() 9 { 10 int n; 11 while(scanf("%d",&n)!=EOF) 12 { 13 if(n==0) 14 break; 15 for(int i=1;i<=n;i++) 16 scanf("%d",&a[i]); 17 int m; 18 scanf("%d",&m); 19 if(m<5) 20 printf("%d\n",m); 21 else 22 { 23 int mm=m-5; 24 sort(a+1,a+n+1); 25 for(int i=0;i<=mm;i++) 26 dp[i]=0; 27 for(int i=1;i<n;i++) 28 for(int j=mm;j>=a[i];j--) 29 dp[j]=max(dp[j],dp[j-a[i]]+a[i]); 30 int ans=0; 31 for(int i=0;i<=mm;i++) 32 if(dp[i]>ans) 33 ans=dp[i]; 34 printf("%d\n",m-ans-a[n]); 35 } 36 } 37 return 0; 38 }
4.uva.562.Dividing Coins
平衡问题,先累加硬币的总价值,然后sum/2,作为背包容量对n个硬币进行选择,求出其最大价值。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAXN=105; 5 const int MAXM=30000; 6 int dp[MAXM]; 7 int coin[MAXN]; 8 int main() 9 { 10 int test; 11 scanf("%d",&test); 12 while(test--) 13 { 14 int n; 15 scanf("%d",&n); 16 int sum=0; 17 for(int i=1;i<=n;i++) 18 { 19 scanf("%d",&coin[i]); 20 sum+=coin[i]; 21 } 22 int half=sum/2; 23 for(int i=0;i<=half;i++) 24 dp[i]=0; 25 for(int i=1;i<=n;i++) 26 for(int j=half;j>=coin[i];j--) 27 dp[j]=max(dp[j],dp[j-coin[i]]+coin[i]); 28 int cnt=0; 29 for(int i=0;i<=half;i++) 30 if(dp[i]>cnt) 31 cnt=dp[i]; 32 half=sum-cnt; 33 int ans; 34 if(half>cnt) 35 ans=half-cnt; 36 else 37 ans=cnt-half; 38 printf("%d\n",ans); 39 } 40 return 0; 41 }
5.hdu.2955.Robberies.
被抓的概率比较难算,加之精度问题,所以转换为不被抓的概率。
若以概率为代价,不是整数,无法作为下标,所以以银行总价值为背包容量,单个银行的储蓄为体积,以不被抓的概率作为价值。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAXN=105; 5 const int MAXM=11000; 6 double dp[MAXM]; 7 int money[MAXN]; 8 double pro[MAXN]; 9 int main() 10 { 11 int test; 12 scanf("%d",&test); 13 while(test--) 14 { 15 int n; 16 double P; 17 scanf("%lf%d",&P,&n); 18 P=1.0-P; 19 int sum=0; 20 for(int i=1;i<=n;i++) 21 { 22 scanf("%d%lf",&money[i],&pro[i]); 23 sum+=money[i]; 24 pro[i]=1.0-pro[i]; 25 } 26 for(int i=0;i<=sum;i++) 27 dp[i]=0; 28 dp[0]=1; 29 for(int i=1;i<=n;i++) 30 for(int j=sum;j>=money[i];j--) 31 dp[j]=max(dp[j],dp[j-money[i]]*pro[i]); 32 int ans=0; 33 for(int i=0;i<=sum;i++) 34 if(dp[i]>=P&&i>ans) 35 ans=i; 36 printf("%d\n",ans); 37 } 38 return 0; 39 }
6.HDU1087
题意:在一串数列中,找出一串数字要严格递增的子序列(不用连续),使得该子序列的和为最大值。
dp[i]表示以a[i] 为结束元素的子序列中和最大的一组的和。
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 5 const int maxn=1010; 6 7 int dp[maxn]; 8 9 int a[maxn]; 10 11 int main() 12 { 13 int n; 14 while(cin>>n) 15 { 16 if(!n) 17 break; 18 19 for(int i=1;i<=n;i++) 20 cin>>a[i]; 21 22 for(int i=1;i<=n;i++) 23 dp[i]=a[i]; 24 25 for(int i=1;i<=n;i++) 26 for(int j=1;j<i;j++) 27 if(a[j]<a[i]&&dp[j]+a[i]>dp[i]) 28 dp[i]=dp[j]+a[i]; 29 30 int ans=0; 31 for(int i=1;i<=n;i++) 32 if(ans<dp[i]) 33 ans=dp[i]; 34 35 cout<<ans<<endl; 36 } 37 return 0; 38 }
7.HDU 2571 命运
这道题就是给出一个n*m的矩阵,每个矩阵有一个价值(也可以为负)
规定小明在这个矩阵内可以从(x,y)走到(x+1,y) ,(x,y+1), (x,y*k) ,其中K>1
即小明也可以从该点走到向下一格,或者向右一格,或者向右走到该行的列数是当前列数的倍数的格子。
然后现在小明要从(1,1)走到(n,m)
问最大的价值为多少
dp[i][j]为走到(i,j)时的最大价值
注意初始化, 为-inf,除了dp[1][1]=a[1][1]
刚开始初始化为0,wa了。
先递推第一行和第一列,然后再递推后面。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 7 const int inf=0x3f3f3f3f; 8 const int maxn=23; 9 const int maxm=1010; 10 11 int dp[maxn][maxm]; 12 int a[maxn][maxm]; 13 14 int main() 15 { 16 //freopen("in.txt","r",stdin); 17 18 int test; 19 cin>>test; 20 while(test--) 21 { 22 int n,m; 23 cin>>n>>m; 24 for(int i=1;i<=n;i++) 25 for(int j=1;j<=m;j++) 26 cin>>a[i][j]; 27 28 //刚开始初始化为0,错了,考虑清楚再做题 29 for(int i=1;i<=n;i++) 30 for(int j=1;j<=m;j++) 31 dp[i][j]=-inf; 32 33 dp[1][1]=a[1][1]; 34 for(int i=2;i<=n;i++) 35 dp[i][1]=dp[i-1][1]+a[i][1]; 36 for(int j=2;j<=m;j++) 37 { 38 for(int k=1;k<j;k++) 39 if(j%k==0) 40 dp[1][j]=max(dp[1][j],dp[1][k]+a[1][j]); 41 dp[1][j]=max(dp[1][j],dp[1][j-1]+a[1][j]); 42 } 43 for(int i=2;i<=n;i++) 44 for(int j=2;j<=m;j++) 45 { 46 dp[i][j]=max(dp[i][j-1],dp[i-1][j])+a[i][j]; 47 for(int k=1;k<j;k++) 48 if(j%k==0) 49 dp[i][j]=max(dp[i][j],dp[i][k]+a[i][j]); 50 } 51 52 cout<<dp[n][m]<<endl; 53 } 54 return 0; 55 }
8.HDU 1069 Monkey and banana
题意:有n种箱子,问最多能把箱子堆得多高,要求:上面的箱子的长和宽都要严格小于下面的长和宽。
排序+最大子序列
每种箱子,有x,y,z,全排列6种,所以可以看作是有6n个箱子。
1.按照长,宽从小到大排列
2.dp[i] 表示以第i个箱子为底,最高的高度,
则dp[i]初始化为box[i].z,即第i个箱子上面没有其他箱子时的 高度。
i:1-->n
dp[i]=box[i].z; // 初始化
j:-->i-1 // 查看一次
if( 可以放 )
dp[i]=max(dp[i],dp[j]+box[i].z);
若第j 个箱子满足放在i上的条件。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn=33; 7 8 int dp[maxn*6]; 9 10 struct Box 11 { 12 int x,y,z; 13 }box[maxn*6]; 14 15 int tot; 16 17 void addedge(int x,int y,int z) 18 { 19 box[tot].x=x; 20 box[tot].y=y; 21 box[tot++].z=z; 22 } 23 24 bool cmp(Box a,Box b) 25 { 26 if(a.x==b.x) 27 return a.y<b.y; 28 return a.x<b.x; 29 } 30 31 int main() 32 { 33 int n; 34 int cas=1; 35 36 while(cin>>n) 37 { 38 if(!n) 39 break; 40 41 int a,b,c; 42 43 tot=1; 44 45 for(int i=1;i<=n;i++) 46 { 47 cin>>a>>b>>c; 48 49 addedge(a,b,c); 50 addedge(a,c,b); 51 addedge(b,a,c); 52 addedge(b,c,a); 53 addedge(c,a,b); 54 addedge(c,b,a); 55 } 56 57 tot--; 58 59 sort(box+1,box+tot+1,cmp); 60 61 for(int i=1;i<=tot;i++) 62 dp[i]=box[i].z; 63 64 for(int i=1;i<=tot;i++) 65 for(int j=1;j<i;j++) 66 if(box[j].x<box[i].x&&box[j].y<box[i].y) 67 dp[i]=max(dp[i],dp[j]+box[i].z); 68 69 int ans=0; 70 71 for(int i=1;i<=tot;i++) 72 if(ans<dp[i]) 73 ans=dp[i]; 74 75 cout<<"Case "<<cas++<<": maximum height = "<<ans<<endl; 76 } 77 return 0; 78 }
9.HDU 1171 Bing Event in HDU
题意:n种物品,每种的价值为val,有num个,
现在要将所有物品分成A,B 2份,要求,A,B尽量相等,但要保证A>=B
化为01背包
B=sum/2
将B作为背包最大容量
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn=5100; 7 const int maxv=125100; 8 9 int dp[maxv]; 10 int v[maxn]; 11 12 int main() 13 { 14 int n; 15 while(cin>>n) 16 { 17 if(n<0) 18 break; 19 20 int tot=1; 21 22 int val,num; 23 24 for(int i=1;i<=n;i++) 25 { 26 cin>>val>>num; 27 for(int j=1;j<=num;j++) 28 v[tot++]=val; 29 } 30 31 int sum=0; 32 33 for(int i=1;i<tot;i++) 34 sum+=v[i]; 35 36 int B=sum/2; 37 38 memset(dp,0,sizeof(dp)); 39 40 for(int i=1;i<tot;i++) 41 for(int j=B;j>=v[i];j--) 42 { 43 dp[j]=max(dp[j],dp[j-v[i]]+v[i]); 44 } 45 46 int ans_b=0; 47 for(int i=0;i<=B;i++) 48 if(dp[i]>ans_b) 49 ans_b=dp[i]; 50 51 cout<<sum-ans_b<<" "<<ans_b<<endl; 52 } 53 return 0; 54 }
10.HDU 2084 数塔
先初始化最后一行,然后从后往前递推
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 5 const int maxn=105; 6 7 int a[maxn][maxn]; 8 int dp[maxn][maxn]; 9 10 int main() 11 { 12 int test; 13 cin>>test; 14 while(test--) 15 { 16 int n; 17 cin>>n; 18 for(int i=1;i<=n;i++) 19 for(int j=1;j<=i;j++) 20 cin>>a[i][j]; 21 22 for(int j=1;j<=n;j++) 23 dp[n][j]=a[n][j]; 24 for(int i=n-1;i>0;i--) 25 for(int j=1;j<=i;j++) 26 dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+a[i][j]; 27 28 cout<<dp[1][1]<<endl; 29 30 } 31 return 0; 32 }
11.HDU 1176 免费馅饼
这道题和数塔一样de
把时间看成行,点看成列,就是和数塔一样递推了
注意,这里把所有输入的点x++,是为了不用对边界的递推进行另外处理
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxT=100000+10; 7 8 int dp[maxT][13]; 9 int a[maxT][13]; 10 11 int main() 12 { 13 int n; 14 while(scanf("%d",&n)) 15 { 16 if(!n) 17 break; 18 19 memset(a,0,sizeof(a)); 20 21 int t,x; 22 int maxt=0; 23 for(int i=1;i<=n;i++) 24 { 25 scanf("%d%d",&x,&t); 26 x++; 27 a[t][x]++; 28 if(t>maxt) 29 maxt=t; 30 } 31 32 for(int j=1;j<=11;j++) 33 dp[maxt][j]=a[maxt][j]; 34 35 for(int i=maxt-1;i>=0;i--) 36 for(int j=1;j<=11;j++) 37 dp[i][j]=max(max(dp[i+1][j-1],dp[i+1][j]),dp[i+1][j+1])+a[i][j]; 38 39 printf("%d\n",dp[0][6]); 40 41 } 42 return 0; 43 }
12.HDU 1203 I need a offer
也是简单的01背包
至少一个学校offer的概率,就等于1-一个都没有的概率
注意2个小细节,写在注释
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn=10000+10; 7 8 double dp[maxn]; 9 double pro[maxn]; //申请不到的概率 10 int cost[maxn]; 11 12 int main() 13 { 14 int n,m; 15 while(scanf("%d%d",&n,&m)) 16 { 17 if(!n&&!m) 18 break; 19 20 21 for(int i=1;i<=m;i++) 22 { 23 scanf("%d%lf",&cost[i],&pro[i]); 24 pro[i]=1.0-pro[i]; 25 } 26 27 28 //刚开始用memset(dp,1.0,sizeof(dp)); 29 //但是数组并没有被初始化为1.0 30 //注意这里,memset慎用 31 32 for(int i=0;i<=n;i++) 33 dp[i]=1.0; 34 35 for(int i=1;i<=m;i++) 36 for(int j=n;j>=cost[i];j--) 37 dp[j]=min(dp[j],dp[j-cost[i]]*pro[i]); 38 39 double ans=1.0; 40 41 for(int i=0;i<=n;i++) 42 if(dp[i]<ans) 43 ans=dp[i]; 44 45 //刚开始用printf("%.1f%\n",100-ans*100); 46 //wa了 47 48 printf("%.1f%%\n",100-ans*100); 49 50 } 51 return 0; 52 }
13.HDU2159 fate
好题
题意:小明升级需要n的经验,但是他的忍耐度只有m,每杀一只怪会减掉一些忍耐度,m用完了,小明就不再继续玩下去了,而且,小明最多只杀s只怪。
现在有k种怪,每种怪无数只,每种怪有相应的经验val,和忍耐度b
现在问小明能不能升级,能的话,最多还可以剩下多少忍耐度。
这道是2维代价的完全背包
经验n:价值
忍耐度m和杀怪数s:代价
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn=105; 7 8 int dp[maxn][maxn]; 9 int val[maxn]; //相应的经验 10 int b[maxn]; //相应的忍耐度 11 12 int main() 13 { 14 int n,m,kind,s; 15 16 while(cin>>n) 17 { 18 cin>>m>>kind>>s; 19 for(int i=1;i<=kind;i++) 20 cin>>val[i]>>b[i]; 21 22 memset(dp,0,sizeof(dp)); 23 24 25 //选择杀不杀第k种怪后, 26 //付出代价为i,杀的怪数为j时得到的最大经验为dp[i][j] 27 for(int k=1;k<=kind;k++) 28 for(int i=b[k];i<=m;i++) 29 for(int j=1;j<=s;j++) 30 dp[i][j]=max(dp[i][j],dp[i-b[k]][j-1]+val[k]); 31 32 int ans=10000; 33 34 //在得到的经验>=n的条件下付出的忍耐度i尽量小 35 //则剩下的忍耐度会尽量大 36 for(int i=0;i<=m;i++) 37 for(int j=0;j<=s;j++) 38 if(dp[i][j]>=n&&i<ans) 39 ans=i; 40 41 ans=m-ans; //求出剩下的忍耐度 42 if(ans<0) 43 cout<<-1<<endl; 44 else 45 cout<<ans<<endl; 46 47 } 48 49 return 0; 50 }
14.HDU 2577 How to Type
题意:给出一串字符串(只有大小写字母),问在keyboard上打出最少需要多少个按钮。
2个数组,
on[i] 表示打完第i个字母后CapsLock开着
off[i] 表示打完第i个字母后CapsLock关着
初始化:
on[i]=1
off[i]=0
注意最后 on[len]++
因为最后还要把CapsLock关了
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cctype> 5 using namespace std; 6 7 const int maxn=105; 8 9 int off[maxn]; 10 11 int on[maxn]; 12 13 int main() 14 { 15 int test; 16 17 cin>>test; 18 19 while(test--) 20 { 21 char str[maxn]; 22 23 cin>>str; 24 25 int len=strlen(str); 26 27 off[0]=0; 28 on[0]=1; 29 30 for(int i=1;i<=len;i++) 31 { 32 if(islower(str[i-1])) 33 { 34 on[i]=min(off[i-1]+2,on[i-1]+2); 35 36 off[i]=min(off[i-1]+1,on[i-1]+2); 37 } 38 else{ 39 40 on[i]=min(off[i-1]+2,on[i-1]+1); 41 42 off[i]=min(off[i-1]+2,on[i-1]+2); 43 } 44 } 45 46 on[len]++; 47 48 int ans=off[len]<on[len]?off[len]:on[len]; 49 50 cout<<ans<<endl; 51 52 } 53 54 return 0; 55 56 }
15. HDU 1159 Common Subsequence
题意:给出2个字符串
求出这2个字符串的最长公共子序列 LCS
dp[i][j]表示在比较s的第i个字符和t的第j个字符后的最大值
考虑2个字符相同和不同的情况
dp的下标从1开始的话可以省去很多的初始化
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 7 const int maxn=500; 8 9 int dp[maxn][maxn]; 10 11 char s[maxn]; 12 char t[maxn]; 13 14 int main() 15 { 16 while(cin>>s>>t) 17 { 18 int lenS=strlen(s); 19 int lenT=strlen(t); 20 21 memset(dp,0,sizeof(dp)); 22 23 for(int i=1;i<=lenS;i++) 24 for(int j=1;j<=lenT;j++) 25 { 26 if(s[i-1]==t[j-1]) 27 dp[i][j]=dp[i-1][j-1]+1; 28 else 29 dp[i][j]=max(dp[i-1][j],dp[i][j-1]); 30 } 31 32 cout<<dp[lenS][lenT]<<endl; 33 34 } 35 36 return 0; 37 }
16. HDU 1421 搬寝室
题意:现在有n件物品,小明要把其中的2*k件搬去其他宿舍,
小明每次拿2件物品,疲劳值为2件的质量之差的平方
现在问小明搬完这2*k件后,疲劳值最小为多少
思路:先排序,再dp
dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]);
注意初始化
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 5 using namespace std; 6 7 #define LL long long 8 9 const LL inf=100000000; 10 const int maxn=2010; 11 12 LL dp[maxn][maxn]; 13 LL a[maxn]; 14 15 int main() 16 { 17 int n,k; 18 while(cin>>n>>k) 19 { 20 for(int i=1;i<=n;i++) 21 cin>>a[i]; 22 23 sort(a+1,a+n+1); 24 25 // for(int i=2;i<=n;i++) 26 // b[i]=(a[i]-a[i-1])*(a[i]-a[i-1]); 27 28 for(int i=1;i<=n;i++) 29 for(int j=1;j<=k;j++) 30 dp[i][j]=inf; 31 32 dp[0][0]=0; 33 34 for(int i=2;i<=n;i++) 35 //j=k开始不合逻辑 36 for(int j=i/2;j>=1;j--) 37 dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1])); 38 39 cout<<dp[n][k]<<endl; 40 } 41 42 return 0; 43 }
17. HDU 1864 最大报销额
题意:给你n张发票,和最大的报销额为sum,
每张发票有m件物品,满足一定条件的发票就可以报销,
现在问你这些发票的最大报销额是多少
01背包
对每一张发票进行判断,若可以报销则把这张发票的总额加入到数组money[tot++]
tot--
然后把tot这么多张发票作为物品
同时把tot作为背包容量
dp后,找出满足dp[i]<=sum中的dp[i]的最大值
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 using namespace std; 6 7 const int maxn=33; 8 9 double dp[30010]; 10 double money[maxn]; 11 12 int main() 13 { 14 15 double sum; 16 int n; 17 18 while(cin>>sum>>n) 19 { 20 if(!n) 21 break; 22 23 int tot=1; 24 25 for(int j=1;j<=n;j++) 26 { 27 int m; 28 double a=0.0,b=0.0,c=0.0; 29 double cnt; 30 char str; 31 char strstr; 32 bool flag=true; 33 34 cin>>m; 35 36 for(int i=1;i<=m;i++) 37 { 38 cin>>str>>strstr>>cnt; 39 if(str=='A') 40 a+=cnt; 41 else if(str=='B') 42 b+=cnt; 43 else if(str=='C') 44 c+=cnt; 45 else 46 flag=false; 47 } 48 49 if(flag&&a<=600.00&&b<=600.00&&c<=600.00&&a+b+c<=1000.00) 50 money[tot++]=a+b+c; 51 } 52 53 memset(dp,0,sizeof(dp)); 54 tot--; 55 56 for(int i=1;i<=tot;i++) 57 for(int j=tot;j>0;j--) 58 dp[j]=max(dp[j],dp[j-1]+money[i]); 59 60 double ans=0; 61 for(int i=1;i<=tot;i++) 62 if(dp[i]<=sum&&dp[i]>ans) 63 ans=dp[i]; 64 65 printf("%.2f\n",ans); 66 } 67 return 0; 68 }
18.