吐槽:這題目起的好隨便啊
原題
小明在業餘時間喜歡打電子遊戲,不是星際和魔獸這些,是賽爾號一類的遊戲。最近小明在玩一款新出的遊戲,叫做■■■■■■■■。小明覺得遊戲裏自己的裝備太垃圾了,每次都被大神虐,一怒之下充了■■元準備強化裝備。
這個遊戲中用於強化裝備的道具叫做強化符文。有以下3 種:
- 賦值強化符文,對某個裝備使用這個符文以後,裝備威力值會變爲一個常數。因爲這個功能很IMBA,可以讓一個垃圾裝備變得非常牛■,所以它在遊戲裏很稀有,市場上最多能見到一個。
- 加法強化符文,對某個裝備使用後,威力值加上一個常數。
- 乘法強化符文,對某個裝備使用後,威力值乘上一個常數。
市場上有M 個不同強化符文可以購買,小明有N 件裝備準備強化,他只能購買K 個強化符文,然後以任意順序使用這些符文,強化他的任意裝備(一個裝備可以不強化也可以強化多次)。根據遊戲的設定,所有裝備威力值乘積爲總效果。請爲他設計一個購買和強化方案,使強化後的所有裝備總效果值最大。
由於小明RP 不太好,打BOSS 都不掉神裝,所以他的裝備不超過兩件。
題目大意(有改動) |
---|
給你一個含N個元素的序列,有m個修改操作,每個操作有兩個參數:type,c。 |
當type=1時,表示把某元素賦爲c |
當type=2時,表示把某元素加上c |
當type=3時,表示把某元素乘上c |
求使用k個不同操作可以獲得的序列元素乘積的最大值,值可能很大,請輸出 |
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。
幾個顯然的事實
- 看看數據範圍,,不用想,這肯定是題目的切入點 。
- 所以加法應該優先於乘法使用,賦值優於加法
- 加、乘法都好,無論怎麼分配,選權值大的就是王道
我一開始,以爲答案是加起來,就無從下手。
後來,我才發現總威力是乘積。
那就很好辦了。。。
首先,乘法無論作用於第一個還是第二個,效果是一樣的。所以,乘法的問題可以單獨解決。
其次,這題顯然用DP,加法部分的結果含有乘法,不好處理,考慮到數據範圍
輸入數據中所有數不超過2000。
不會超過
如果設表示選了個,,的最大值。
不僅空間複雜度可行,也順便解決了乘法難轉移的問題。
只是時間複雜度。。。。
涼定了?????
NO
- 加、乘法都好,無論怎麼分配,選權值大的就是王道
按爲第一關鍵字爲第二關鍵字排序以後,不論選了幾個,肯定都集中在前面。
時間複雜度降至
結果
爆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;
}