JZOJ 4245. 【五校联考6day2】er

题目

Description

小明在业余时间喜欢打电子游戏,不是星际和魔兽这些,是赛尔号一类的游戏。最近小明在玩一款新出的游戏,叫做■■■■■■■■。小明觉得游戏里自己的装备太垃圾了,每次都被大神虐,一怒之下充了■■元准备强化装备。
这个游戏中用于强化装备的道具叫做强化符文。有以下3 种:
1. 赋值强化符文,对某个装备使用这个符文以后,装备威力值会变为一个常数。因为这个功能很IMBA,可以让一个垃圾装备变得非常牛■,所以它在游戏里很稀有,市场上最多能见到一个。
2. 加法强化符文,对某个装备使用后,威力值加上一个常数。
3. 乘法强化符文,对某个装备使用后,威力值乘上一个常数。
市场上有M 个不同强化符文可以购买,小明有N 件装备准备强化,他只能购买K 个强化符文,然后以任意顺序使用这些符文,强化他的任意装备(一个装备可以不强化也可以强化多次)。根据游戏的设定,所有装备威力值乘积为总效果。请为他设计一个购买和强化方案,使强化后的所有装备总效果值最大。
由于小明RP 不太好,打BOSS 都不掉神装,所以他的装备不超过两件。
 

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 4
3 2

Sample Output

4.159
 

Data Constraint

对于20% 的数据,N = 1;
对于全部数据M,K ≤ 100;N ≤ 2,最多一个Type_i = 1。
输入数据中所有数不超过2000。

 

分析

  • 出看这道题嗯,代码量很大

  • 打了暴力,却忘了精度问题
  • 我们首先要知道一个小知识:log(a*b)=log(a)+log(b)
  • 这样乘法就解决了
  • 然后就是一个DP,设f[i][j]为用了i个道具,有了价值为j的最大的第二个道具的值
  • 转移方程就是

    f[i+1][j]=max(f[i][j]+jia[i+1]*j,f[i+1][j]);
    f[i+1][j+jia[i+1]]=max(f[i][j]+jia[i+1]*(sum[i]-j),f[i+1][j+jia[i+1]]);

  • 因为赋值的只有一个,所以我们只需要,枚举就好了

代码

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<cstdio>
  6 #define ll long long
  7 using namespace std;
  8 const int N=110;
  9 int jia[N],che[N],sum[N],f[110][N*2000],maxs[N];
 10 double summ[N];
 11 double ans;
 12 bool  cmp(int a,int b){
 13     return a>b;
 14 }
 15 int main ()
 16 {
 17     ios::sync_with_stdio(false);
 18     int n,m,k;
 19     cin>>n>>m>>k;
 20     int x=0,y=0;
 21     if (n==1)
 22        cin>>x;
 23     else
 24       cin>>x>>y;
 25     int cnt1=0,cnt2=0;
 26     int fff=0;
 27     for (int i=1,b,c;i<=m;i++)
 28     {
 29         cin>>b>>c;
 30         if (b==1)
 31            fff=c;
 32         if (b==2)
 33            jia[++cnt1]=c;
 34         if (b==3)
 35            che[++cnt2]=c;
 36     }
 37     sort(jia+1,jia+1+cnt1,cmp);
 38     sort(che+1,che+1+cnt2,cmp);
 39     sum[0]=x+y;
 40     for (int i=1;i<=k;i++)
 41     {
 42         summ[i]=summ[i-1]+log(che[i]);
 43         sum[i]=sum[i-1]+jia[i];
 44     }
 45     if (n==1)
 46     {
 47        for(int i=0;i<=k;i++)
 48         {
 49             ans=max(ans,log(sum[min(i,cnt1)])+summ[min(k-i,cnt2)]);
 50             if(i!=k&&fff)
 51               ans=max(ans,log(sum[min(i,cnt1)])+summ[min(k-i-1,cnt2)]);
 52         }
 53         printf("%.3lf
",ans);
 54         return 0;
 55     }
 56         memset(f,0xcf,sizeof(f));
 57         f[0][x]=x*y;
 58         for(int i=0;i<=cnt1;i++)
 59         {
 60            for(int j=x;j<=sum[i];j++)
 61            {
 62               f[i+1][j]=max(f[i][j]+jia[i+1]*j,f[i+1][j]);
 63               f[i+1][j+jia[i+1]]=max(f[i][j]+jia[i+1]*(sum[i]-j),f[i+1][j+jia[i+1]]);
 64               maxs[i]=max(maxs[i],f[i][j]);
 65            }
 66         }
 67         for(int u=0;u<=k;u++)
 68             ans=max(ans,log(maxs[min(u,cnt1)])+summ[min(k-u,cnt2)]);
 69         if(fff)
 70        {
 71           k--;
 72           sum[0]=fff+y;
 73           for(int i=1;i<=k;i++)
 74               sum[i]=sum[i-1]+jia[i];
 75           memset(f,0xcf,sizeof(f));
 76           memset(maxs,0,sizeof(maxs));
 77           f[0][fff]=fff*y;
 78           for(int i=0;i<=k;i++)
 79           {
 80             for(int j=fff;j<=sum[i];j++)
 81             {
 82                 f[i+1][j]=max(f[i][j]+jia[i+1]*j,f[i+1][j]);
 83                 f[i+1][j+jia[i+1]]=max(f[i][j]+jia[i+1]*(sum[i]-j),f[i+1][j+jia[i+1]]);
 84                 maxs[i]=max(maxs[i],f[i][j]);
 85             }
 86           }
 87           for(int u=0;u<=k;u++)
 88               ans=max(ans,log(maxs[u])+summ[k-u]);
 89           sum[0]=x+fff;
 90           for(int i=1;i<=k;i++)
 91               sum[i]=sum[i-1]+jia[i];
 92           memset(f,0xcf,sizeof(f));
 93           memset(maxs,0,sizeof(maxs));
 94           f[0][x]=x*fff;
 95           for(int i=0;i<=k;i++)
 96           {
 97               for(int j=x;j<=sum[i];j++)
 98               {
 99                 f[i+1][j]=max(f[i][j]+jia[i+1]*j,f[i+1][j]);
100                 f[i+1][j+jia[i+1]]=max(f[i][j]+jia[i+1]*(sum[i]-j),f[i+1][j+jia[i+1]]);
101                 maxs[i]=max(maxs[i],f[i][j]);
102              }
103          }
104         for(int u=0;u<=k;u++)
105             ans=max(ans,log(maxs[u])+summ[k-u]);
106       }
107     printf("%.3lf",ans);
108 }

 

 

为何要逼自己长大,去闯不该闯的荒唐
原文地址:https://www.cnblogs.com/zjzjzj/p/10334757.html