P3983 塞斯石(9.19)

题面:

戳这里

题意:

①塞斯石是一种重要的东西,以塞斯(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;
}

总结

本题考验的是学生的思维能力,只要把思维从石头转换为船就能轻易解决本道题,事实告诉我们:正着磕不出来的题,可以试试从反面磕一磕,若还是不行,可以考虑开下一题了换个思路再试一试,拿着题就磕容易吃瘪(磕了半小时后的惨痛经验),实在不行就先留着,等下面的题答完后就可以回来接着磕。(这道题如果想不到背包的话,可以试试暴搜拿个部分分)

posted @ 2022-10-04 20:01  zhaozixu2006  阅读(26)  评论(0编辑  收藏  举报