题意
你要配置一杯糖水,每次你可以选择如下几个操作中的一个。
1 加入100 \(A\) 克的水。
2 加入100 \(B\) 克的水。
3 加入 \(C\) 克的糖
4 加入 \(D\) 克的糖
此外,这杯糖水要满足以下几个要求。
1 糖的质量不能超过水的质量的 \(E/100\) 。
2 总质量不能超过 \(F\) 。
在此要求下,你要让这杯糖水的浓度最大。
解法
看到题解里大佬们都用的枚举操作,我讲一下用 \(DP\) 的做法,实际上是因为考试大标题写的 \(DP\) 。
用了两个数组, \(F\) 求出糖可以达到的数目, \(g\) 求出水可以到达的数目,之后列举糖的数目,从满足浓度条件的所需的最少的水开始,一直加到超过质量要求为止。中间找到一个可行的水的质量时,便可以停止(高浓度优先)。这样不断比较即可。
代码
#include<bits/stdc++.h>
using namespace std;
int a,b,c,d,e,f,F[4001],g[4000],anss,anst,anscz,ss,tt,cz;//cz的比较是因为考试题多了个限制条件
int main()
{
//freopen("easy.in","r",stdin);
//freopen("easy.out","w",stdout);
cin>>a>>b>>c>>d>>e>>f;
anss=10000000;
anscz=10000000;
a*=100;
b*=100;
for(int i=1;i<=f;i++)F[i]=2e9,g[i]=2e9;
for(int i=c;i<=f;i++)F[i]=min(F[i],F[i-c]);
for(int i=d;i<=f;i++)F[i]=min(F[i],F[i-d]);//糖
for(int j=a;j<=3500;j+=100)g[j]=min(g[j],g[j-a]+1);
for(int j=b;j<=3500;j+=100)g[j]=min(g[j],g[j-b]);//水
for(int i=1;i*(100+e)<=f*e;i++){
if(!F[i]){//可行糖
int mn;
if((i*100)%e==0)mn=(i*100)/e;
else mn=(i*100)/e+1;//向上取整
if(mn%100!=0)mn=100*(mn/100)+100;//整百方便枚举
for(int j=mn;j+i<=f;j+=100){
if(g[j]!=2e9){//可行水
ss=j;
tt=i;
cz=g[j];
break;
}
}
if(((anst*ss<anss*tt)||(anst*ss==anss*tt&&cz<anscz)||(anst*ss==anss*tt&&ss<anss&&cz==anscz))&&(ss+tt)<=f){//限制条件较多,考试没spj ,此题应该只用第一个判断
anst=tt;
anss=ss;
anscz=cz;
}
}
}
if(anss==10000000){//对于我的初始赋值较大要整一下 ,不然不知不觉超f
if(b<=f){
cout<<b<<" "<<0<<endl;
return 0;
}
if(a<=f){
cout<<a<<" "<<0<<endl;
return 0;
}
cout<<0<<" "<<0<<endl;
return 0;
}
cout<<anss+anst<<" "<<anst<<endl;
}
/*
1 2 10 20 4 610
7 12 7 9 67 3000
12 15 25 30 2 1524
*/