zoukankan      html  css  js  c++  java
  • P1412 经营与开发

    题目描述

    4X概念体系,是指在PC战略游戏中一种相当普及和成熟的系统概念,得名自4个同样以“EX”为开头的英语单词。

    eXplore(探索)

    eXpand(拓张与发展)

    eXploit(经营与开发)

    eXterminate(征服)

    ——维基百科

    今次我们着重考虑exploit部分,并将其模型简化:

    你驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞过n个星球。

    星球笼统的分为2类:资源型和维修型。(p为钻头当前能力值)

    1.资源型:含矿物质量a[i],若选择开采,则得到a[i]*p的金钱,之后钻头损耗k%,即p=p*(1-0.01k)

    2.维修型:维护费用b[i],若选择维修,则支付b[i]*p的金钱,之后钻头修复c%,即p=p*(1+0.01c)

    注:维修后钻头的能力值可以超过初始值(你可以认为是翻修+升级)

    金钱可以透支。

    请作为舰长的你仔细抉择以最大化收入。

    输入输出格式

    输入格式:

    第一行4个整数n,k,c,w。

    以下n行,每行2个整数type,x。

    type为1则代表其为资源型星球,x为其矿物质含量a[i];

    type为2则代表其为维修型星球,x为其维护费用b[i];

    输出格式:

    一个实数(保留2位小数),表示最大的收入。

    输入输出样例

    输入样例#1: 复制
    5 50 50 10
    1 10
    1 20
    2 10
    2 20
    1 30
    
    输出样例#1: 复制
    375.00

    说明

    【数据范围】

    对于30%的数据 n<=100

    另有20%的数据 n<=1000;k=100

    对于100%的数据 n<=100000; 0<=k,c,w,a[i],b[i]<=100;保证答案不超过10^9

    先上30分的代码(三维数组空间开不了那么大)

    三维

    f(i,j,k)代表前i个,开采j个,维护k个的最大价值

    设p1,p2为那两个固定系数

    t=1

    f(i,j,k)=max(f(i-1,j,k),f(i-1,j-1,k)+p1^(j-1)*p2^k*a[i])

    t=2

    f(i,j,k)=max(f(i-1,j,k),f(i-1,j,k-1)+p1^j*p2^(k-1)*a[i])

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define inf 2147483647
    const ll INF = 0x3f3f3f3f3f3f3f3fll;
    #define ri register int
    template <class T> inline T min(T a, T b, T c)
    {
        return min(min(a, b), c);
    }
    template <class T> inline T max(T a, T b, T c)
    {
        return max(max(a, b), c);
    }
    template <class T> inline T min(T a, T b, T c, T d)
    {
        return min(min(a, b), min(c, d));
    }
    template <class T> inline T max(T a, T b, T c, T d)
    {
        return max(max(a, b), max(c, d));
    }
    #define pi acos(-1)
    #define me(x, y) memset(x, y, sizeof(x));
    #define For(i, a, b) for (int i = a; i <= b; i++)
    #define FFor(i, a, b) for (int i = a; i >= b; i--)
    #define mp make_pair
    #define pb push_back
    const int maxn = 100005;
    #define mod 100003
    const int N=200;
    
    // name*******************************
    double f[N][N][N];
    double p1,p2;
    int n;
    double k,c,w;
    int t[N];
    double a[N],b[N];
    double ans=0;
    int s1[N];
    int s2[N];
    // function******************************
    double qmul(double a,int b)
    {
        double base=a;
        double ans=1;
        while(b)
        {
            if(b&1)
                ans*=base;
            base*=base;
            b>>=1;
        }
        return ans;
    }
    
    //***************************************
    int main()
    {
    //    freopen("test.txt","r",stdin);
        cin>>n>>k>>c>>w;
        For(i,1,n)
        {
            s1[i]=s1[i-1];
            s2[i]=s2[i-1];
            cin>>t[i];
            if(t[i]==1)
            {
                cin>>a[i];
                s1[i]++;
            }
            else
            {
                cin>>b[i];
                s2[i]++;
            }
        }
        p1=1-0.01*k;
        p2=1+0.01*c;
        fill(&f[0][0][0],&f[N-1][N-1][N-1],-inf);
    
        f[0][0][0]=0;
        For(i,1,n)
        {
            For(j,0,s1[i])
            {
                For(k,0,s2[i])
                {
                    f[i][j][k]=f[i-1][j][k];
                    if(t[i]==1&&j>=1)
                        f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k]+qmul(p1,j-1)*qmul(p2,k)*a[i]);
                    if(t[i]==2&&k>=1)
                        f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]-qmul(p1,j)*qmul(p2,k-1)*b[i]);
                    ans=max(ans,f[i][j][k]);
    //                cout<<i<<","<<j<<","<<k<<":"<<f[i][j][k]<<endl;
                }
            }
        }
        printf("%.2f",ans*w);
        return 0;
    }
    View Code

    再看一维神奇代码

    逆着走,就能压成一维了!!!

    记最终答案为ans,其实对于每个星球不管是维修还是资源型,都可以把对钻头的改变度记作一个常数k,而且k是有后效性的。

    我们先具一个i=4的例子,

    ans=w*k1*a1+w*k1*k2*a2+w*k1*k2*k3*a3+w*k1*k2*k3*k4*a4,

    即ans=w*(k1*a1+k1*k2*a2+k1*k2*k3*a3+k1*k2*k3*a4),

    进一步提公因式就是ans=w*(k1*(a[1]+k2*(a[2]+k3*(a[3]+k4*a[4]))))

    所以我们发现从最里面往外面走是最好的,也就是逆着推,真特么神奇

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define inf 2147483647
    const ll INF = 0x3f3f3f3f3f3f3f3fll;
    #define ri register int
    template <class T> inline T min(T a, T b, T c)
    {
        return min(min(a, b), c);
    }
    template <class T> inline T max(T a, T b, T c)
    {
        return max(max(a, b), c);
    }
    template <class T> inline T min(T a, T b, T c, T d)
    {
        return min(min(a, b), min(c, d));
    }
    template <class T> inline T max(T a, T b, T c, T d)
    {
        return max(max(a, b), max(c, d));
    }
    #define pi acos(-1)
    #define me(x, y) memset(x, y, sizeof(x));
    #define For(i, a, b) for (int i = a; i <= b; i++)
    #define FFor(i, a, b) for (int i = a; i >= b; i--)
    #define mp make_pair
    #define pb push_back
    const int maxn = 100005;
    #define mod 100003
    const int N=100005;
    
    // name*******************************
    int n;
    double f[N];
    double k,c,w;
    int t[N];
    double a[N],b[N];
    double ans=-inf;
    // function******************************
    
    
    //***************************************
    int main()
    {
    //    freopen("test.txt","r",stdin);
    
        scanf("%d%lf%lf%lf",&n,&k,&c,&w);
        For(i,1,n)
        {
            scanf("%d",&t[i]);
            if(t[i]==1)
                scanf("%lf",&a[i]);
            else
                scanf("%lf",&b[i]);
        }
        double p1=1-0.01*k;
        double p2=1+0.01*c;
        For(i,0,n)
        f[i]=-inf;
        f[n+1]=0;
        FFor(i,n,1)
        {
            if(t[i]==1)
                f[i]=max(f[i+1],f[i+1]*p1+a[i]);
            else
                f[i]=max(f[i+1],f[i+1]*p2-b[i]);
        }
        printf("%.2f",f[1]*w);
    
        return 0;
    }
  • 相关阅读:
    PAT 1097. Deduplication on a Linked List (链表)
    PAT 1096. Consecutive Factors
    PAT 1095. Cars on Campus
    PAT 1094. The Largest Generation (层级遍历)
    PAT 1093. Count PAT's
    PAT 1092. To Buy or Not to Buy
    PAT 1091. Acute Stroke (bfs)
    CSS:word-wrap/overflow/transition
    node-webkit中的requirejs报错问题:path must be a string error in Require.js
    script加载之defer和async
  • 原文地址:https://www.cnblogs.com/planche/p/8659533.html
Copyright © 2011-2022 走看看