破解石碑(区间动规)

  1. 破解石碑 (stele.cpp/c/pas)
    【问题描述】 相传在上古时期留下了许多块神秘的石碑,石碑的正面按顺序刻上 N 个数 字,并且每个数字的下方都有一个字号较小的数相对应。研究人员把上面的数 字称为 A 列,下面的数字称为 B 列。 在查阅古书后人们得知,每块石碑其实都是一把锁。如果人们在石碑上按 合适的方法对数字进行操作,就会获得巨大的能量。操作的规则如下: 若 Ai和 Ai + 1 不互质,我们可以在原石碑中抹去第 i 和第 i + 1 个数(包括 A 中和 B 中),然后将两个序列重新按顺序编号。 假如最终 B 列中被抹去的数的和达到可能的最大值,这把巨锁就解开了。 由于对石碑上数字的抹去是不可逆的,为了不浪费每块石碑,我们必须事先计 算出每块石碑的操作方案并获得 B 列被删去的可能最大和。
    全国信息学奥林匹克联赛(NOIP2016)Day 1 信烨教育
    第 3 页 共 4 页

【输入】 第 1 行一个整数 N; 第 2 行 N 个整数,依次表示 Ai; 第 3 行 N 个整数,依次表示 Bi。

【输出】 仅含一个整数,表示 B 列被删去的可能最大和。

【输入输出样例】 stele.in stele.out 6 9 8 6 5 6 3 11 19 12 17 18 15 64

【数据范围】 对于 30%的数据,N ≤ 20; 对于 60%的数据,N ≤ 100; 对于 80%的数据,N ≤ 500 对于 100%的数据,N ≤ 800, 1 ≤ Ai, Bi ≤ 109。

program df;
var i,j,n,m,x,y,z,k,l,r:longint;
a,b:array[0..1000] of longint;
sum:array[0..1000] of int64;
f:array[0..1000,0..1000] of int64;
g:array[0..1000,0..1000] of boolean;
function gcd(x,y:longint):longint;
begin
if y=0 then exit(x)
else gcd:=gcd(y,x mod y);
end;

begin
assign(input,’stele.in’);
reset(input);
assign(output,’stele.out’);
rewrite(output);
fillchar(g,sizeof(g),false);
readln(n);
for i:=1 to n do
read(a[i]);
for i:=1 to n do
if gcd(a[i],a[i+1])>1 then g[i,i+1]:=true;
readln;
for i:=1 to n do
begin
read(b[i]);
sum[i]:=sum[i-1]+b[i];
end;
for i:=2 to n do
if g[i-1,i] then f[i-1,i]:=b[i-1]+b[i];

for i:=n downto 1 do
for j:=i+1 to n do
for k:=i+1 to j-1 do
if (i<>j) and (k<>i) and (k<>j) then
if ((g[i,k]) and (g[k+1,j])) or ((g[i+1,j-1]) and (gcd(a[i],a[j])>1)) //i到k能消除,k+1到j能消除,则i到j能消除,或者,i+1到j-1能消除,i,j不互质,则i到j能消除
then
begin
g[i,j]:=true;
f[i,j]:=sum[j]-sum[i-1];
end;
for i:=n downto 1 do
for j:=i+1 to n do
for k:=i to j do
if f[i,j]小于f[i,k]+f[k+1,j] then f[i,j]:=f[i,k]+f[k+1,j]; //max函数会超时
writeln(f[1,n]);
close(input);
close(output);
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值