1. 程式人生 > >2018年10月31日提高組 T2 B

2018年10月31日提高組 T2 B

大意

給定 n n 個數,若合併相鄰兩個數 a i , a i

+ 1 a_i,a_{i+1} 的代價為 a i × a
i + 1 a_i\times a_{i+1}
,然後變成 a i
a_i
,求合併所有數的代價


思路

比較容易想到一種不能 A A 的局面貪心

直接找到最小值,然後合併即可,複雜度 O ( n ) O(n) ,期望得分:30,實際得分:80


這種貪心錯誤的原因很明顯啊,所以我們想到了另一種貪心

列舉所有的數,然後計算左邊的數合併起來的最小代價,右邊的數合併起來的最小代價,再合併即可,時間複雜度: O ( n 2 ) O(n^2) ,期望得分:100,實際得分:100


聽大佬說還可以區間 d p 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);//輸出
	}
}