破解石碑 (动态规划)

该博客探讨了古代石碑上的数字谜题,其中涉及动态规划算法解决如何通过特定操作最大化B列数字之和的问题。根据输入的石碑数字,通过计算找到最佳抹除策略,以达到最大的和。

破解石碑

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

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

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

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

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

用g数组记录i,j两个点能否在一起(i,j之间的数字都被抹去),用f数组记录从i到j得到的最大答案。

program mys;
var t,h,i,j,k,m,n:longint;
g:array[0..900,0..900]of longint;
f:array[0..900,0..900]of int64;
a,b:array[0..1000]of longint;
sum:array[0..1000]of int64;

function gcd(a,b:longint):longint;
begin
if a mod b=0 then exit(b)
else exit(gcd(b,a mod b));
end;

begin 
assign(input,'stele.in');reset(input);
assign(output,'stele.out');rewrite(output);
readln(n);
read(a[1]);
for i:=2 to n do 
begin 
read(a[i]);
if gcd(a[i],a[i-1])>1 then g[i-1,i]:=1;
end;

for i:=1 to n do 
begin 
read(b[i]);
sum[i]:=sum[i-1]+b[i];
end;
for i:=1 to n do 
if g[i-1,i]=1 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(i<>k)and(j<>k) then 
if ((g[i,k]=1) and (g[k+1,j]=1))or ((g[i+1,j-1]=1) and (gcd(a[i],a[j])>1)) then 
begin
g[i,j]:=1;
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];
writeln(f[1,n]);
close(input);
close(output);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值