正题
题目大意
nnn个武器(n≤2n\leq2n≤2),mmm个符文
符文1:直接改变一个武器的攻击力(最多一个)
符文2:增加一个武器的攻击力
符文3:使一个人的武器攻击力翻若干倍
求武器攻击力乘积最大,输出答案的自然对数。
解题思路
首先log(ab)=log(a)+log(b)log(ab)=log(a)+log(b)log(ab)=log(a)+log(b)
然后乘积的就不管,最后答案加上就好了,我们只考虑前两种
n=1n=1n=1时直接暴力枚举选多少加攻击的。
n=2n=2n=2时我们考虑dpdpdp。首先我们肯定选大的,主要考虑哪个加在哪个上面。
fi,jf_{i,j}fi,j表示前iii个符文,第一个武器攻击力为jjj时的武器威力乘积。我们维护一下前缀和就可以计算第二个武器的攻击力
若加在第一个符文上fi,j=min{fi−1,j−addi+addi∗(sumi−j)}f_{i,j}=min\{f_{i-1,j-add_i}+add_i*(sum_i-j)\}fi,j=min{fi−1,j−addi+addi∗(sumi−j)}
若加在第二个符文上fi,j=min{fi−1,j+addi∗j}f_{i,j}=min\{f_{i-1,j}+add_i*j\}fi,j=min{fi−1,j+addi∗j}
然后转移。
之后暴力枚举加的符文选几个,其他都选乘的。
对于符文1,直接处理333次
codecodecode
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=110;
int n,m,k,add[N],sum[N],cnt1,cnt2,mul[N];
int fff,f[N][N*2000],maxs[N],a1,a2;
double ans,summ[N];
bool cmp(int x,int y)
{return x>y;}
int main()
{//freopen("data.in","r",stdin);//freopen("data.out","w",stdout);scanf("%d%d%d",&n,&m,&k);scanf("%d",&a1);if(n==2) scanf("%d",&a2);for(int i=1;i<=m;i++){int x,t;scanf("%d%d",&t,&x);if(t==1) fff=x;if(t==2) add[++cnt1]=x;if(t==3) mul[++cnt2]=x;}sort(add+1,add+1+cnt1,cmp);sort(mul+1,mul+1+cnt2,cmp);sum[0]=a1+a2;for(int i=1;i<=k;i++){summ[i]=summ[i-1]+log(mul[i]);sum[i]=sum[i-1]+add[i];}if(n==1){for(int i=0;i<=k;i++){ans=max(ans,log(sum[min(i,cnt1)])+summ[min(k-i,cnt2)]);if(i!=k&&fff)ans=max(ans,log(sum[min(i,cnt1)])+summ[min(k-i-1,cnt2)]);}printf("%.3lf\n",ans);return 0;}memset(f,0xcf,sizeof(f));f[0][a1]=a1*a2;for(int i=0;i<=cnt1;i++){for(int j=a1;j<=sum[i];j++){f[i+1][j]=max(f[i][j]+add[i+1]*j,f[i+1][j]);f[i+1][j+add[i+1]]=max(f[i][j]+add[i+1]*(sum[i]-j),f[i+1][j+add[i+1]]);maxs[i]=max(maxs[i],f[i][j]);}}for(int u=0;u<=k;u++){int mu=min(k-u,cnt2);ans=max(ans,log(maxs[min(u,cnt1)])+summ[mu]);}if(fff){k--;sum[0]=fff+a2;for(int i=1;i<=k;i++)sum[i]=sum[i-1]+add[i];memset(f,0xcf,sizeof(f));memset(maxs,0,sizeof(maxs));f[0][fff]=fff*a2;for(int i=0;i<=k;i++){for(int j=fff;j<=sum[i];j++){f[i+1][j]=max(f[i][j]+add[i+1]*j,f[i+1][j]);f[i+1][j+add[i+1]]=max(f[i][j]+add[i+1]*(sum[i]-j),f[i+1][j+add[i+1]]);maxs[i]=max(maxs[i],f[i][j]);}}for(int u=0;u<=k;u++){int mu=k-u;ans=max(ans,log(maxs[u])+summ[mu]);}sum[0]=a1+fff;for(int i=1;i<=k;i++)sum[i]=sum[i-1]+add[i];memset(f,0xcf,sizeof(f));memset(maxs,0,sizeof(maxs));f[0][a1]=a1*fff;for(int i=0;i<=k;i++){for(int j=a1;j<=sum[i];j++){f[i+1][j]=max(f[i][j]+add[i+1]*j,f[i+1][j]);f[i+1][j+add[i+1]]=max(f[i][j]+add[i+1]*(sum[i]-j),f[i+1][j+add[i+1]]);maxs[i]=max(maxs[i],f[i][j]);}}for(int u=0;u<=k;u++){int mu=k-u;ans=max(ans,log(maxs[u])+summ[mu]);}}printf("%.3lf",ans);
}