COCI 2016/2017 Round #3 T4 Kvalitetni

目錄

題目

分析

代碼


題目

分析

我會說這道題最難的其實是讀題嗎???(讀題讀了1h+)

可能是翻譯問題,反正是沒講清楚,我解釋一下:

1.所有類似於"(?)"的表達式的最大值Z1(啊啊啊是Z1不是Zi啊)

2.在表達式(()+()+()+......)或者(()*()*()*()*......)有k項,則這個表達式裏所有元素的總和的最大值爲Zk(是不是被繞暈了)

3.表達式只有全是+或者全是*(不用處理計算的先後問題了)


好了好了,我們終於把題看懂了,下面是做法:

首先,用的方式來處理括號其實就是用函數遞歸了

然後,在函數內部,用數組來儲存其中的k個表達式的最大值

最後呢,就是在每一個括號內部,計算目前括號的最大值。

下面是處理乘法的方式:

 

衆所周知,

顯然,

可以證明,在總和爲sum的k個數中,要使得它們的乘積最大,要使它們平均分配纔可以。

(平均分配:每個數都是sum/k)

但是,還有一個問題,就是我們有的元素有最大值啊。

那我們就還是儘量平均分配,取不到sum/k的就取它的最大值,然後把它差的數,添到其它數上面(乾坤大挪移!!!)

代碼

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>

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<double> 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<siz;i++)
					if(!vis[i])
					{
						if(c[i] < maxi)
						{
							ans[i] = c[i];
							vis[i]=1;
							cntno++;
							maxi += (maxi-c[i])/(siz-cntno);
							i=-1;
							continue;
						}
						else
							ans[i]=maxi;
					}
				
				double res=ans[0];
				for(int i=1;i<siz;i++)
					res *= ans[i];
				return res;
			}
		}
	}
}

int main()
{
//	freopen("kvalitetni.in","r",stdin);
//	freopen("kvalitetni.out","w",stdout);
	scanf("%d",&k);
	for(int i=1;i<=k;i++)
		scanf("%lf",&z[i]);
	
	scanf("\n%s",sca+1);
	len=strlen(sca+1);
	
	double ans=Calc();
	printf("%.6f\n",ans);
	return 0;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章