2023.04.08-春招-玩具打包

https://codefun2000.com/p/P1168
题目内容
塔子哥开的玩具店生意越来越好,每天都有很多客人前来选购玩具。有一天,他接到了一个大单,客户想购买 \(n\) 个玩具,并且要求打包成多个玩具袋。塔子哥精心为客户挑选了 \(n\) 个玩具,并且将它们编号为\(1,2,\dots,n\)

然而,塔子哥发现这个订购单还有一个要求:每个玩具袋最多只能装 \(m\) 个玩具,并且同一个玩具袋里装的玩具编号必须是连续的。玩具袋的成本与容积成线性关系。

为了解决这个问题,他决定采用样本中点估计的方法来计算玩具袋的容积。具体来说,如果一个玩具袋中装的最大的玩具容积是 \(u\),最小的是 \(v\),那么这个玩具袋的成本就是\(k \times floor((u+v)/2) +s\),其中 kk 是玩具袋中装入玩具的个数,ss 是一个常数,\(floor(x)\) 是下取整函数,比如 floor(3.8)=3,floor(2)=2

客户并没有规定玩具袋的数量,但是希望玩具袋的成本越小越好,毕竟买玩具就很贵了。请求出塔子哥打包这 \(n\) 个玩具所用的最小花费。

输入描述
第一行三个正整数 \(n,m,s\) 。意义如题面所示

第二行 \(n\) 个正整数 \(a_1,a_2,...,a_n\),表示每个玩具的体积。

对于全部数据,\(1\le n \le 10^4\)\(1\le m \le 10^3\)\(m \le n , 1 \le a_i, s \le 10^4\)

输出描述
输出一个整数,表示打包这 \(n\) 个玩具玩具袋的最小成本。

样例
输入
6 4 3
1 4 5 1 4 1
输出
21
样例解释
前三个玩具装成一个玩具袋,后三个玩具装成一个玩具袋。

题目大意:
这个题就是给你一个数组a,最多连续的m个数可以捆绑在一起并且权值为\(k \times floor((min+max)/2) +s\),min为捆绑在一起的数的最大值,max为捆绑在一起的最大值。捆绑的堆数没有限制,问将这个n个数全部捆绑最小值。

定义f[i]为打包前i个玩具的最小花费,然后我们看数据范围,可以两层for循环,\(dp[i]=dp[j-1]+k \times floor((min+max)/2) +s\),其中\(j \in [max(1,i-m+1),i]\)
然后我们就是算这个min和max,这个时候我们定义_max[i][j]为区间[i,j]的最大值,_min[i][j]为区间[i,j]的最小值。然后用区间dp算一下

#include<iostream>
#include<algorithm>
#include<cstring> 
using namespace std;
typedef long long ll;
const int maxn=5e5+100;
const int N=1e4+100,M=1e3+100;
int a[maxn];
int dp[maxn];
int _min[N][M],_max[N][M],n,m,s;
int main(){
	memset(_min,0x3f3f3f3f,sizeof(_min));
	cin>>n>>m>>s;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int len=1;len<=m;len++){
		for(int i=1;i+len-1<=n;i++){
			int j=i+len-1;
			if(len==1){
				_min[i][j]=_max[i][j]=a[i];
			}else{
                _min[i][j]=min(_min[i][j-1],a[j]);
                _max[i][j]=max(_max[i][j-1],a[j]);
			}
		}
	}
	for(int i=1;i<=n;i++){
		dp[i]=0x3f3f3f3f;
		for(int j=max(1,i-m+1);j<=i;j++){
			int ma=_max[j][i];
			int mi=_min[j][i];
			int p=(i-j+1)*((ma+mi)/2)+s;
			dp[i]=min(dp[i],dp[j-1]+p);
		}
	}
	cout<<dp[n]<<endl;
}

这里我们也可以优化一下,可以从后往前枚举 然后一边枚举一边更新最大值和最小值 计算转移答案(如果不想一边转移一边枚举也可以使用区间DP的方式预处理一下[i,j]区间的最大值和最小值)

#include<iostream>
#include<algorithm>
#include<cstring> 
using namespace std;
typedef long long ll;
const int maxn=5e5+100;
ll a[maxn];
ll dp[maxn];
int main(){
	ll n,m,s;
	cin>>n>>m>>s;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		dp[i]=1e18;
		ll ma=0,mi=1e18;
		for(int j=i;j>=max(1ll,i-m+1);j--){
			ma=max(ma,a[j]);
			mi=min(mi,a[j]);
			ll p=(i-j+1)*((ma+mi)/2)+s;
			dp[i]=min(dp[i],dp[j-1]+p);
		}
	}
	cout<<dp[n]<<endl;
}
posted @ 2024-05-04 21:22  lipu123  阅读(12)  评论(0)    收藏  举报