2018年10月31日提高組 T2 B
阿新 • • 發佈:2018-11-03
大意
給定 個數,若合併相鄰兩個數 的代價為 ,然後變成 ,求合併所有數的代價
思路
比較容易想到一種不能 的局面貪心
直接找到最小值,然後合併即可,複雜度 ,期望得分:30,實際得分:80
這種貪心錯誤的原因很明顯啊,所以我們想到了另一種貪心
列舉所有的數,然後計算左邊的數合併起來的最小代價,右邊的數合併起來的最小代價,再合併即可,時間複雜度: ,期望得分:100,實際得分:100
聽大佬說還可以區間 ,可本蒟蒻不會啊。。。
程式碼
#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);//輸出
}
}