题意

你要配置一杯糖水,每次你可以选择如下几个操作中的一个。

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
*/
posted on 2021-08-28 21:22  漠寒·  阅读(33)  评论(0编辑  收藏  举报