【五校联考6day2】er

这题首先是:

分类讨论

首先,我们可以知道,最优解一定是先“1”再“2”后“3”!(为什么自己想)
然后,我们可以发现,要是选的话,一定是从大选到小(为什么自己想)
嗯嗯,n=1的情况是很简单的,然后我们考虑n=2的//o(*  ̄︶ ̄ * )o//
n=2的我们可以DP!!!
有两种做法:
第一种:(简单又自然,就是有点慢)
在这里插入图片描述
我们设f[j]表示当前(就是前i个)这个东西是否能够构成。
这样子就是转移的话很费时间。(┭┮﹏┭┮)

但能过(O(∩_∩)O哈哈~)

上标:

#include<cstdio>
#include<algorithm>
#include<cmath>
#define ll long long
#define db double
using namespace std;
int n,M,K,a[11],e=0,p[310],m0=0,p0=0;
int f[200010];
db s,ans=0,m[310];

inline int read()
{
	int x=0,f=0; char c=getchar();
	while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return f ? -x:x;
}

inline int cmp(int x,int y) {return x>y;} 

inline int cmp1(db x,db y) {return x>y;}

int main()
{
	n=read(),M=read(),K=read();
	for (int i=1;i<=n;i++) a[i]=read();
	for (int i=1,x,y;i<=M;i++)
	{
		x=read(),y=read();
		if (x==1) {e=y; continue;}
		if (!y) continue;
		if (x==2) p[++p0]=y;
		else m[++m0]=log(y);
	}
	sort(p+1,p+p0+1,cmp);
	sort(m+1,m+m0+1,cmp1);
	for (int i=2;i<=p0;i++) p[i]+=p[i-1];
	for (int i=2;i<=m0;i++) m[i]+=m[i-1];
	if (n==1)
	{
		for (int i=0;i<=min(K,p0);i++)
		{
			ans=std::max(ans,log(p[i]+a[1])+m[std::min(K-i,m0)]);
			if (i<K) ans=std::max(ans,log(p[i]+e)+m[std::min(K-i-1,m0)]);
		}
		printf("%.3lf
",ans);
	}
	else
	{
		f[0]=1;
		for (int i=0;i<=min(K,p0);i++)	
		{
			for (int j=p[p0];j>=p[i]-p[i-1];j--)
				f[j]=max(f[j],f[j-p[i]+p[i-1]]);
			for (int j=0;j<=p[i];j++)
				if (f[j] && f[p[i]-j])
				{
					ans=std::max(ans,log(j+a[1])+log(p[i]-j+a[2])+m[std::min(K-i,m0)]);
					ans=std::max(ans,log(j+a[2])+log(p[i]-j+a[1])+m[std::min(K-i,m0)]);
					ans=std::max(ans,log(j+e)+log(p[i]-j+std::max(a[1],a[2]))+m[std::min(K-i-1,m0)]);
					ans=std::max(ans,log(j+std::max(a[1],a[2]))+log(p[i]-j+e)+m[std::min(K-i-1,m0)]);
				}
		}
		printf("%.3lf
",ans);
	}
	return 0;
}

第二种:(有人说很容易想到。。。)
我们设f[i][j]表示前i个加法东东
然后我们可以将其转移到:
f[i+1][j+p[i]]=max(~,f[i][j]);
f[i+1][j]=max(~,f[i][j]+p[i]);
然后赋值东东就自己特判一下就好了。
上标:(为了跑快点不惜一切代价(但就是不吸!o( ̄ヘ ̄o#)))

#include<cstdio>
#include<algorithm>
#include<cmath>
#define db double
using namespace std;
int n,M,K,a[11],e=0,p[310],m0=0,p0=0;
int f[110][202010],now;
db s,ans=0,m[310],sum[110];

inline int read()
{
	int x=0,f=0; char c=getchar();
	while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return f ? -x:x;
}

inline int cmp(int x,int y) {return x>y;} 

inline int cmp1(db x,db y) {return x>y;}

int main()
{
	freopen("er.in","r",stdin);
	freopen("er.out","w",stdout);
	n=read(),M=read(),K=read();
	a[1]=read();
	if (n>1)
	{
		a[2]=read();
		if (a[1]>a[2]) swap(a[1],a[2]);
	}
	for (int i=1,x,y;i<=M;i++)
	{
		x=read(),y=read();
		if (x==1) {e=y; continue;}
		if (!y) continue;
		if (x==2) p[++p0]=y;
		else m[++m0]=std::log(y);
	}
	sort(p+1,p+p0+1,cmp);
	sort(m+1,m+m0+1,cmp1);
	for (int i=2;i<=m0;i++) m[i]+=m[i-1];
	if (n==1)
	{
		for (int i=0;i<=min(K,p0);i++)
		{
			ans=std::max(ans,log(p[i]+a[1])+m[std::min(K-i,m0)]);
			if (i<K) ans=std::max(ans,log(p[i]+e)+m[std::min(K-i-1,m0)]);
		}
		printf("%.3lf
",ans);
	}
	else
	{
		f[0][a[1]]=a[2];now=e+p[1];
		f[1][a[1]+p[1]]=std::max(f[1][a[1]+p[1]],f[0][a[1]]);
		f[1][a[1]]=std::max(f[1][a[1]],f[0][a[1]]+p[1]);
		sum[0]=std::max(sum[0],1.0*f[0][a[1]]*a[1]);
		for (int i=1;i<p0;i++)
		{
			now+=p[i+1];
			for (int j=0;j<=now;j++)
				if (f[i][j])
				{
					f[i+1][j+p[i+1]]=std::max(f[i+1][j+p[i+1]],f[i][j]);
					f[i+1][j]=std::max(f[i+1][j],f[i][j]+p[i+1]);
					sum[i]=std::max(sum[i],1.0*f[i][j]*j);
					sum[i]=std::max(sum[i],f[i-1][j]*(j-a[1]+e)*1.0);
				}
		}
		for (int i=0;i<=now;i++)
			sum[p0]=std::max(sum[p0],f[p0][i]*i*1.0);
		for (int i=0;i<=K;i++)
			if (sum[i]) sum[i]=std::log(sum[i]);
		ans=max(ans,sum[K]);
		for (int i=1;i<=std::min(m0,K);i++)
			if (sum[K-i]) ans=std::max(ans,sum[K-i]+m[i]);
		printf("%.3lf
",ans);
	}
	return 0;
}
转载需注明出处。
原文地址:https://www.cnblogs.com/jz929/p/11817605.html