2018年10月31日提高组 T2 B

30 篇文章 0 订阅

大意

给定 n n n个数,若合并相邻两个数 a i , a i + 1 a_i,a_{i+1} ai,ai+1的代价为 a i × a i + 1 a_i\times a_{i+1} ai×ai+1,然后变成 a i a_i ai,求合并所有数的代价


思路

比较容易想到一种不能 A A A的局面贪心

直接找到最小值,然后合并即可,复杂度 O ( n ) O(n) O(n),期望得分:30,实际得分:80


这种贪心错误的原因很明显啊,所以我们想到了另一种贪心

枚举所有的数,然后计算左边的数合并起来的最小代价,右边的数合并起来的最小代价,再合并即可,时间复杂度: O ( n 2 ) O(n^2) O(n2),期望得分:100,实际得分:100


听大佬说还可以区间 d p dp dp,可本蒟蒻不会啊。。。


代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ri register int
#define min(a,b) (a)<(b)?(a):(b)
using namespace std;int t,n;
long long ans,a[301],f[301];
inline void tx(register int x)
{
	long long s=0;
	memcpy(f,a,sizeof(f));
	for(register int i=1;i<n;i++)//合并左边的数
	if(f[i]!=x&&f[i+1]!=x&&f[i]>f[i+1]&&x*f[i+1]+f[i]*f[i+1]<x*f[i])
	{
		s+=f[i]*f[i+1];
		f[i]=f[i+1];
	}
	for(register int i=2;i<=n;i++)//合并右边的数
	if(f[i]!=x&&f[i-1]!=x&&f[i]>f[i-1]&&x*f[i-1]+f[i]*f[i-1]<x*f[i])
	{
		s+=f[i]*f[i-1];
		f[i]=f[i-1];
	}
	for(register int i=1;i<=n;i++) if(f[i]!=x) s+=f[i]*x;//最后即为区间最小值
	ans=min(ans,s);//保存最小值
	return;
}
signed main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);ans=99999999999999ll;
		for(ri i=1;i<=n;i++) scanf("%lld",&a[i]);
		for(ri i=1;i<=n;i++) tx(a[i]);//判断是否可以
		printf("%lld\n",ans);//输出
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值