P3983 赛斯石(赛后强化版)-动态规划

真程海洋近来需要进购大批赛斯石,你或许会问,什么是赛斯石?

首先我们来了解一下赛斯,赛斯是一个重量单位,我们用si作为其单位。比如1赛斯就是1si。

而赛斯石有这样一个性质,它本来是一赛斯一赛斯单独存在的,但是用自然枪将其精化之后,它就会与其它经过精化的赛斯石进行合并,合并到合适的重量之后,便将其钝化,使其不再合并其它赛斯石,如果合错了,也可以用金刚刀将其切开(神奇的是你只能切成整数赛斯重量)。赛斯石的重量只能是整数赛斯重量,而不同赛斯重量的赛斯石的价格也是不一样的

现需上市N赛斯重量的赛斯石,卖家想算出这些赛斯石经过某种合并方式来获得的最大收益。然而目前有一个问题,市场在真程大殿附近(真程海洋中心位置),卖家需要租船送赛斯石过去(即不考虑卖家自己租船过去的费用),目前有十种船可以租,载重量从1si到10si,每艘船的租价也是有所不同的,如下表所示:

由于真程大殿附近有强烈的赛斯力,导致无法对赛斯石进行任何操作,商家将赛斯石运过来之后就只能按照之前合并好的卖。假设卖家不返回,且这些赛斯石全部能卖出去。现在卖家他要计算总盈利(设总盈利=赛斯石的总收益-租船所需总费用),请你设计一个程序,算出一种最佳方案,以获得最大总盈利

https://www.luogu.org/problemnew/show/P3983

状态:f[i]表示i si的最大总盈利;

难点:一艘船可以运好几个石头,有些小石头还能合成大石头可能更赚

先dp处理小石头合成大石头能得到的最大利润;

a[i]表示i si的最多能卖多少钱

a[i+j]=max(a[i+j],a[i]+a[j]);

再减去对于每种i的船费。

再来一次背包即可

f[i]=max(f[i],f[i-j]+a[j]);

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#define inf 1e18+5
#define ll long long
using namespace std;
int inline read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n;
int s[11]={0,1,3,5,7,9,10,11,14,15,17};
ll a[11];
ll f[100001];
int main()
{
    n=read();
    for(int i=1;i<=10;i++){
        a[i]=read();
    }
    for(int i=1;i<=10;i++){
        for(int j=1;j<=i;j++){
            if(i+j<=10) a[i+j]=max(a[i+j],a[i]+a[j]);
        }
    }
    for(int i=1;i<=10;i++){
        a[i]-=s[i];
    }
    memset(f,-127,sizeof(f));
    f[0]=0;
    for(int i=0;i<=n;i++){
        for(int j=1;j<=10;j++){
            if(i-j>=0) f[i]=max(f[i],f[i-j]+a[j]);
        }
    }
    printf("%lld",f[n]);
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值