COCI 2016/2017 Round #3 T4 Kvalitetni

目录

题目

分析

代码


题目

COCI 2016/2017 Round #3 T4 Kvalitetni_第1张图片

分析

我会说这道题最难的其实是读题吗???(读题读了1h+)

可能是翻译问题,反正是没讲清楚,我解释一下:

1.所有类似于"(?)"的表达式的最大值Z1(啊啊啊是Z1不是Zi啊)

2.在表达式(()+()+()+......)或者(()*()*()*()*......)有k项,则这个表达式里所有元素的总和的最大值为Zk(是不是被绕晕了)

3.表达式只有全是+或者全是*(不用处理计算的先后问题了)


好了好了,我们终于把题看懂了,下面是做法:

首先,用的方式来处理括号其实就是用函数递归了

然后,在函数内部,用数组来储存其中的k个表达式的最大值

最后呢,就是在每一个括号内部,计算目前括号的最大值。

下面是处理乘法的方式:

 

众所周知,

显然,

可以证明,在总和为sum的k个数中,要使得它们的乘积最大,要使它们平均分配才可以。

(平均分配:每个数都是sum/k)

但是,还有一个问题,就是我们有的元素有最大值啊。

那我们就还是尽量平均分配,取不到sum/k的就取它的最大值,然后把它差的数,添到其它数上面(乾坤大挪移!!!)

代码

#include
#include
#include
#include

using namespace std;

const int N=50,L=1e6;

int k,len,p=1;
double z[N+5];
char sca[L+5];

double Calc()
{
	if(sca[p++] != '(') return 0;
	vector c;
	bool f=0; //0->+,1->*
	char now;
	while(now = sca[p++])
	{
		if(now=='(')
			p--,c.push_back(Calc());
		if(now=='?')
			c.push_back(z[1]);
		if(now=='+')
			f=0;
		if(now=='*')
			f=1;
		if(now==')')
		{
			if(!f)
			{
				double r1=0,r2=0;
				r1=z[c.size()];
				for(int i=c.size()-1;i>=0;i--)
					r2+=c[i];
				return min(r1,r2);
			}
			else
			{
				int siz=c.size(),cntno=0;
				bool vis[N+5];
				double maxi=z[c.size()]/siz,ans[N+5];
				
				memset(vis,0,sizeof vis);
				
				for(int i=0;i

 

 

你可能感兴趣的:(COCI 2016/2017 Round #3 T4 Kvalitetni)