题面:
戳这里
题意:
①塞斯石是一种重要的东西,以塞斯(Si)为单位。
②本来是单独存在,经过特殊处理后可以合并,合并后也可以切开
③现在有一定量(Need)的塞斯石需要上市,卖家需要租船送赛斯石过去,目前有十种船可以租,载重量从 1Si 到 10si ,每艘船的租价也是有所不同的,如下表所示:
④给定 1Si ~ 10Si 的市场价,求完成后的最大利润
说人话:
给你一定的需求,可以合并,每个Si都有相对的代价,求合并完后的最大利润
(可以试着正着思考10min再食用效果更佳)
思路:
10min过去了,你会发现正着做几乎不可取(你要是非想正着写我也不拦着),要处理的因素太多,合并和分解有点难搞,那我们换种方法来:
①石头可以分割但是船不可以
例子:比如说4Si可以分割成
1+1+1+1Si
1+1+2Si
1+3Si
2+2Si
4Si
②最后可以选择总和为Need的船,且每个船的利益都是固定的
例子:不需要
通过上述两点,开动你聪明的小脑瓜看看这是什么道什么题
相信聪明(bushi)的你已经看出来这是个完全背包了(而且还是很裸的那种),看不出来的可以考虑退役了
接下来就是喜闻乐见的代码了(就是一个不用动脑子的板子)
#include<bits/stdc++.h>
using namespace std;
long long 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 a[12];
int b[12]={0,1,3,5,7,9,10,11,14,15,17};//对于船价直接打表
long long f[100010];//f和dp数组一定要开long long不然只有96(血的教训)
long long dp[100010];
int main()
{
n=read();
for(int i=1;i<=10;i++)
{
a[i]=read();//读入市场价
}
for(int i=1;i<=10;i++)
{
for(int j=i;j<=10;j++)
{
f[j]=max(f[j],f[j-i]+a[i]);//总重量为j时最大收益
}
}
for(int i=1;i<=n;i++) f[i]-=b[i];//利益
for(int i=1;i<=10;i++)//完全背包的板子
{
for(int j=i;j<=n;j++)
{
dp[j]=max(dp[j],dp[j-i]+f[i]);
}
}
cout<<dp[n]<<endl;
return 0;
}