JZOJ 4245【五校聯考6day2】er

吐槽:這題目起的好隨便啊

原題

小明在業餘時間喜歡打電子遊戲,不是星際和魔獸這些,是賽爾號一類的遊戲。最近小明在玩一款新出的遊戲,叫做■■■■■■■■。小明覺得遊戲裏自己的裝備太垃圾了,每次都被大神虐,一怒之下充了■■元準備強化裝備。
這個遊戲中用於強化裝備的道具叫做強化符文。有以下3 種:

  1. 賦值強化符文,對某個裝備使用這個符文以後,裝備威力值會變爲一個常數。因爲這個功能很IMBA,可以讓一個垃圾裝備變得非常牛■,所以它在遊戲裏很稀有,市場上最多能見到一個。
  2. 加法強化符文,對某個裝備使用後,威力值加上一個常數。
  3. 乘法強化符文,對某個裝備使用後,威力值乘上一個常數。
    市場上有M 個不同強化符文可以購買,小明有N 件裝備準備強化,他只能購買K 個強化符文,然後以任意順序使用這些符文,強化他的任意裝備(一個裝備可以不強化也可以強化多次)。根據遊戲的設定,所有裝備威力值乘積爲總效果。請爲他設計一個購買和強化方案,使強化後的所有裝備總效果值最大。
    由於小明RP 不太好,打BOSS 都不掉神裝,所以他的裝備不超過兩件。
題目大意(有改動)
給你一個含N個元素的序列(N2)(N\leqslant2),有m個修改操作,每個操作有兩個參數:type,c。
當type=1時,表示把某元素賦爲c
當type=2時,表示把某元素加上c
當type=3時,表示把某元素乘上c
求使用k個不同操作可以獲得的序列元素乘積的最大值,值可能很大,請輸出ln(ans)\ln(ans)

Input

第一行3 個正整數N;M;K, 含義見題面。
第二行N 個正整數Ai,表示他的每個裝備的初始威力值。
第三行開始共M 行,每行兩個正整數Type_i;Ci,描述一個強化符文。Type_i表示符文類型,1 表示賦值,2 表示加法,3 表示乘法。Ci 是對應的常數值。

Output

一個數,表示最大的總效果值。由於這個數可能很大,請輸出它的自然對數,保留3 位小數。

Sample Input

2 5 3
0 1
2 3
2 1
2 4
3 2

Sample Output

4.159

Data Constraint

對於20% 的數據,N = 1;
對於全部數據M,K ≤ 100;N ≤ 2,最多一個Type_i = 1。
輸入數據中所有數不超過2000。

幾個顯然的事實

  1. 看看數據範圍,n2n\leqslant 2,不用想,這肯定是題目的切入點 。
  2. a(bx+c)>ab(x+c)a(bx+c) >ab(x+c)所以加法應該優先於乘法使用,賦值優於加法
  3. 加、乘法都好,無論怎麼分配,選權值大的就是王道

我一開始,以爲答案是加起來,就無從下手。
後來,我才發現總威力是乘積。
那就很好辦了。。。

首先,乘法無論作用於第一個還是第二個,效果是一樣的。所以,乘法的問題可以單獨解決。
其次,這題顯然用DP,加法部分的結果含有乘法,不好處理,考慮到數據範圍

輸入數據中所有數不超過2000。

Ai+typei=2ciA_i+\sum_{type_{i}=2} c_{i}不會超過2000×100=2000002000\times 100=200000
如果設fi,jf_{i,j}表示選了ii個,A1=jA_1=j,A2A_2的最大值。
不僅空間複雜度可行,也順便解決了乘法難轉移的問題。
只是時間複雜度。。。。
O(n2ci)O(n^2\sum c_i)

涼定了?????

NO

  1. 加、乘法都好,無論怎麼分配,選權值大的就是王道

typetype爲第一關鍵字cc爲第二關鍵字排序以後,不論選了幾個,肯定都集中在前面。
時間複雜度降至O(nci)O(n\sum c_i)

結果

爆0。。。
至於原因。。。
爆零部分代碼:

		while(type[i]<mt||(type[i]==mt&&c[i]>mc)) i++;
		while(type[j]>mt||(type[j]==mt&&c[i]<mt)) j--;
		//                                ^  ^^不爆0纔怪

最終:

#include<cstdio>
#include<cstring>
#include<math.h>
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
#define ln(x) (log(x))
using namespace std;
int A[4];
int type[110],c[300];
long long f[110][200010];
double maxf[110];
void qsort(int l,int r)
{
	int i=l,j=r,mt=type[(l+r)/2],mc=c[(l+r)/2],t;
	while(i<=j)
	{
		while(type[i]<mt||(type[i]==mt&&c[i]>mc)) i++;
		while(type[j]>mt||(type[j]==mt&&c[j]<mc)) j--;
		if(i<=j)
		{
			t=type[i];type[i]=type[j];type[j]=t;
			t=c[i];c[i]=c[j];c[j]=t;
			i++;j--;
		}
	}
	if(i<r) qsort(i,r);
	if(l<j) qsort(l,j);
}
int main()
{
	//freopen("er.in","r",stdin);
	//freopen("er.out","w",stdout);
	int n,m,k,i,j,sta;double nans=0;
	scanf("%d%d%d",&n,&m,&k);
	A[2]=1;
	for(i=1;i<=n;i++) scanf("%d",&A[i]);
	for(i=1;i<=m;i++) scanf("%d%d",&type[i],&c[i]);
	qsort(1,m);
	memset(f,-1,sizeof(f));
	maxf[0]=ln(A[2]*A[1]);f[0][A[1]]=A[2];
	for(i=1;i<=k;i++)
	{
		if(type[i]>2) break;
		if(type[i]==1) for(j=0;j<=c[i];j++) f[i][c[i]]=max(f[i][c[i]],f[i-1][j]);
		for(j=0;j<=200000;j++)
		{
			if(type[i]==1&&f[i-1][j]>=0&&n==2) f[i][j]=max(f[i][j],c[i]);
			if(type[i]==2)
			{
				if(j>=c[i]) f[i][j]=max(f[i-1][j-c[i]],f[i][j]);
				if(f[i-1][j]>=0&&n==2) f[i][j]=max(f[i][j],f[i-1][j]+c[i]);
	 		//	printf("%d %d %d\n",i,j,f[i][j]);
			}
		}
		maxf[i]=-1000000.0;
		for(j=0;j<=200000;j++)
			if(ln(f[i][j]*j)>maxf[i]) maxf[i]=ln(f[i][j]*j);
	}
	for(sta=1;sta<=m;sta++)
		if(type[sta]>2) break;
	double sum=0,ans=0;
	for(i=m+1;i<=2*m;i++) c[i]=1;
	for(i=sta;i-sta<=k;i++)
	{
		if(i-sta>k) break;
		nans=-10000000;
		for(j=0;j<=k-(i-sta);j++)
		{
			nans=max(nans,maxf[j]);
		}
		if(ans<nans+sum)ans=nans+sum;
		sum=sum+ln(c[i]);
	}
	printf("%.3lf\n",ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章