B
时间限制:10000MS内存限制:256000KB
题目描述
有 n 个瓶子,它们在桌子上排成一排。第 i 个瓶子的颜色为 ci,每个瓶子都有灵性,每次操作可以选择两个相邻的瓶子,消耗他们颜色的数值乘积的代价将其中一个瓶子的颜色变成另一个瓶子的颜色。
现在要让所以瓶子的颜色都一样,操作次数不限,但要使得操作的总代价最小。
输入
输入文件为 colour.in。
一个测试点内多组数据。
第一行,一个正整数 T,表示数据组数。
每组数据内:
第一行一个整数 n,为瓶子的个数。
第二行共 n 个整数,第 i 个整数为第 i 个瓶子的颜色 ci。
输出
输入文件为 colour.out。
共一行,一个整数,为最小的总代价。
输入样例复制
4
7 4 6 10
输出样例复制
92
样例解释
{7 4 6 10}− > {4 4 6 10}− > {4 4 4 10}− > {4 4 4 4}。
总代价为 7 × 4 + 4 × 6 + 4 × 10 = 92。
说明
Data Constraint 共10个测试点。 对于1,2测试点,n<=3,ci<=10^5; 对于3,4测试点,n<=10,ci<=4; 对于5测试点,n<=300,ci<=4; 对于6测试点,n<=300,ci<=5; 对于7,8,9,10测试点,n<=300,ci<=10^5; 对于所有数据,满足T<=10,n<=300,ci<=10^5,且保证前8个测试点随机。
题解: 贪心。假设将所有瓶子变为c[i],将所有c[i]瓶子标记,则任意两个c[i]瓶子间互不影响
将一个区间变为c[i]有两种策略,一种是将区间直接变为c[i]
第二种是先将区间变为区间最小值,再全部变为c[i](显然只改变一次最优)
将每个区间代价最小相加即为答案
注意:默认a[0]与a[n+1]为当前颜色使代码细节减少
const
maxn=400;
var
a,sum:array[0..maxn+1]of int64;
c:array[1..100000]of boolean;
v:array[0..maxn]of boolean;
b:array[1..maxn,1..maxn]of int64;
ans,sum1,sum2,ssum:int64;
n,i,j,k,len,head,tail,pp,hh,t,hhead,ttail:longint;
function min(a,b:int64):int64;
begin
if a<b then exit(a) else exit(b);
end;
procedure init;
var
i,j:longint;
begin
readln(n);
for i:=1 to n do
begin
read(a[i]);
sum[i]:=sum[i-1]+a[i];
end;
for i:=1 to n do
begin
b[i,i]:=a[i];
for j:=i+1 to n do
b[i,j]:=min(b[i,j-1],a[j]);
end;
ans:=1000000000000;
fillchar(c,sizeof(c),false);
end;
begin
readln(t);
for hh:=1 to t do
begin
init;
for i:=1 to n do
begin
if not c[a[i]] then
begin
ssum:=0;a[0]:=a[i];a[n+1]:=a[i];
fillchar(v,sizeof(v),false);
c[a[i]]:=true;
v[i]:=true;
for j:=0 to n+1 do
if a[j]=a[i] then v[j]:=true;
hhead:=0;
for j:=1 to n+1 do
if (v[j]) then
begin
ttail:=j;
head:=hhead+1;tail:=ttail-1;
if head>tail then
begin
hhead:=j;
continue;
end;
sum1:=0;sum2:=0;len:=0;
// pp:=head;
// if head=1 then pp:=j;
// if tail=j then pp:=head;
for k:=head to tail do
begin
if a[k]<>a[i] then sum1:=sum1+a[k];
if a[k]<>b[head,tail] then
begin
sum2:=sum2+a[k];
//inc(len);
end;
end;
sum1:=sum1*a[i];
sum2:=sum2*b[head,tail]+b[head,tail]*(tail-head+1)*a[i];
ssum:=ssum+min(sum1,sum2);
hhead:=j;
end;
end;
ans:=min(ans,ssum);
end;
writeln(ans);
end;
end.