1. floyd算法的三重循环问题
三层循环的意思。第一层就是加入K的中间点,第二层和第三层循环是求每一对顶点在加入新的点后是否存在距离更近的路径,所以K只能放在最外层。也就是说你再加入新的点后,再进行判断每对顶点是否距离有变,就相当于一个前提条件。
2. 这是noip2006年的第一题
http://games.sina.com.cn/z/d2x/2004-04-20/127447.shtml
3. NOIP2006提高组题:能量项链,求大神指出我的代码逻辑错误
你可能被题目给出的例子给误导了。题目给出的例子:
4
2 3 5 10
也就是:(2,3) (3,5) (5,10) (10,2),最优解刚好是按顺序的,也就是
4和1,炼出的珠子再和2,接着再和3。
因此,你的程序找最优解的算法,就是枚举从任意一颗珠子开始,一直【按一个方向炼制下去】。
因为有N个珠子,因此有N中结果,你就从这个N个结果中找一个最大的,作为最优值。
但是,这个算法是不完整的!!!题目并没说一定要按给出顺序,一直炼制下去!你可以任意挑出两个珠子,只要它们的头和尾一样就可以炼制了。
因此实际的炼制方法,远远多于N。设N颗珠子有F(N)种炼制方法,则:
F(N)=N*F(N-1),N>=3。且 F(1)=0,F(2)=1。
可以统一成:F(N)=N!/2,N>=2。F(1)=0。
题目的N范围:(4<=N<=100),如果采用暴力枚举的话,F(N)会达到很大的数量级。
你要问的,为什么:
7
23 17 212 113 71 301 33
正确结果:31182687
而我代码所产生的结果是:17489304
就是因为你枚举了N=7种情况,实际有7!/2=2520种情况,远远大于你枚举的范围。
通过上面的分析,可以知道,暴力枚举是行不通的。这题就是要用你提到的DP(动态规划来做的)。
用DP(动态规划)的做法是:
1)设有 N 颗珠子,信息保存在 pearls[N]中
2)energy[i][j] 表示从第 i 颗珠子到第 j 颗珠子能获得的最大能量,
初始设置为-1,表示还没有计算出来。
3)当 i==j ,是同一颗珠子,energy[i][j]=0
当 (i+1)%N==j,表示的是两颗相邻的珠子,能获得能量为:
energy[i][j] = pearls[i]*pearls[(i+1)%N]*pearls[(i+2)%N]
其他情况,在 i,j 之间任意选一个位置 k(i<=k<j)断开,计算:
a) 第 i 颗珠子到第 k 颗珠子的最大能量:energy[i,k],
也就是第 k 颗珠子左边所有珠子的最大能量;
b) 第 k+1 颗珠子到第 j 颗珠子的最大能量:energy[k+1,j],
也就是第 k 颗珠子右边所有珠子的最大能量;
c) 第k可珠子左边和右边计算能量后,各剩下一颗珠子,这两颗珠子获得的能量为:
pearls[i]*pearls[k]*pearls[(j+1)%N]
a,b,c三部分的能量相加,就是当选择 k 位置断开后,在珠子 i,j直接能获得的最大能量。
如果这个能量比原来的 energy[i][j] 要大,energy[i][j] 就更新为这个能量值。
4) energy[0][N-1]就是题目要求的,使用N颗珠子能获得的最大能量。
4. 动态规划能量项链的 标程的循环不是很懂,求解释~
题意背景故事略蛋疼啊...其实这个事情的模型就是矩阵相乘吧,只不过对于矩阵来说,一般都是找乘法次数最少的组合,这里是找最多的
首先,你要了解动态规划在这里的思路。先不考虑珠子可以循环这个性质,假设珠子就是1,2,...,N这样,那么我们就是要找(1,2,..,N)之中两两聚合的最大值,这个最大值应该在以下值当中产生:
(1) 和 (2,3,...,N)聚合
(1,2)和(3,4,...N)聚合
....
(1,2,...N-1)和(n)聚合
也就是把1到N一切为二,前半段聚合成一个珠子,后半段聚合成一个珠子,再把聚合后的珠子做一次聚合。至于在哪里一分为二,就是最里面的for循环做的事情。它在i到j之中寻找一个k,使得i到k聚合的能量+(k+1)到j聚合的能量+前面两个聚合出来的珠子聚合的能量 为最大值。而外面的两个for循环,就是在做遍历(i,j)这样的二维组合,先算f(1,2),在算f(2,3)这样只相差1的,然后就可以算f(1,3)这样i,j相差更大的f值了。我们的最终目标是算出f(1,N)的值,也即题目的答案
但是题目还有个条件,就是珠子可以循环,所以我们要在f(1,N),f(2,N+1),f(3,N+2),...,f(N,2N-1)这之间找一个最大值。这也就是为什么一开始 e[N+i]=e[i]; 以及第一个for循环的循环条件是2N-1,至于第二个for循环,就是要保证2点,第一i与j的差距从小到大遍历,第二i与j的差距不超过N,因为你现在数组的长度是2N,但是珠子仍旧只有N颗,防止计算f(1,2N-1)这种无意义的值。
5. 关于NOIP的一道T——能量项链
至少要给个错的原因给我们啊,,还有你都没告诉你这程序是用来干嘛,,这样的话会很费时
6. 求两天学会动态规划的教程,要速成的,为了NOIP复赛,谢谢各位!!!适合信息学竞赛提高组的
你先去看看背包九讲,再去做区间规划题:能量项链,石子合并。做不出看题解。
然后去做线性规划题:拦截导弹,乌龟棋,FBI序列。做完了再做了传纸条,了解
多线程DP。
我就是这么学的,原创不解释,愿楼主采纳
7. 复赛试题—能量项链
Noip2006-1
转载自 宇宙新秀
能量项链
(energy.pas/c/cpp)
很好的一道题目。这道题目在公布成绩之前,曾经是我最有把握的题目。但是,我的这道题目最后没有得分,我不知道是我疯了,还是SDTSC疯了。
很明显是DP。有人说这与那道经典的“石子归并”有些相同。
我们以珠子划分阶段。F[I,J]代表从第i颗珠子到第j颗珠子的合并最大值。tou[i]和wei[i]分别代表珠子i的头部数字和尾部数字。我们很容易得出动态转化方程:
F[I,J]=max(F[I,K]+F[K+1,J]+tou[i]*wei[k]*wei[j]);(1≤i≤n,i≤j≤n,i≤k≤j-1)
边界:F[I,I]=0
最后ANS=F[1,n]
这样的dp时间复杂度为O(n^3).
我们需要每一次枚举项链切开的位置。总共有n种切开的方式,每种方式进行一次dp,而且更新最优结。这样总的时间复杂度为O(n^4)。对付大的数据似乎力不从心。。。。
考虑优化:此题的关键在于将链线性化,从而能够一次dp出解。所以我们把数组开大到n×2;
F[I,J]=max(F[I,K]+F[K+1,J]+tou[i]*wei[k]*wei[j]);(1≤i≤n,i≤j≤n+i,i≤k≤j-1)
边界:F[I,I]=0
最后ANS=max(F[i,i+n-1]); (1≤i≤n)
这样dp一次即可出解,时间复杂度为O(n^3)。
const maxn=100;
var tou,wei:array[1..2*maxn] of integer;
n,i,j,k,p:integer;
f:array[1..maxn*2,1..maxn*2] of longint;
max:longint;
begin
assign(input,'energy.in');
assign(output,'energy.out');
reset(input);
readln(n);
for i:=1 to n do
begin
read(tou[i]);
tou[n+i]:=tou[i];
end;
for i:=1 to n-1 do
begin
wei[i]:=tou[i+1];
wei[i+n]:=wei[i];
end;
wei[n]:=tou[1];
wei[2*n]:=wei[n];
close(input);
fillchar(f,sizeof(f),0);
for p:=1 to n-1 do
for i:=1 to 2*n-2 do
begin
j:=i+p;
if j>2*n-1 then break;
for k:=i to j-1 do
begin
max:=f[i,k]+f[k+1,j]+tou[i]*wei[k]*wei[j];
if f[i,j]<max then
f[i,j]:=max;
end;
end;
for i:=1 to n do
for j:=i to n+i do
if i<>j then
for k:=i to j-1 do
begin
max:=f[i,k]+f[k+1,j]+tou[i]*wei[k]*wei[j];
if max>f[i,j] then f[i,j]:=max;
end;
max:=0;
for i:=1 to n do
if f[i,i+n-1]>max then max:=f[i,i+n-1];
rewrite(output);
writeln(max);
close(output);
end.
8. 求区域性动态规划习题 pascal 最好有题解
tyvj上的乘法游戏,石子归并 能量项链 题解去rqnoj找吧 那里会有人贴出代码
这个是乘法游戏{tyvj}
http://www.tyvj.cn/Problem_Show.aspx?id=1014
9. C语言能量项链问题
举个例子抄说明你的思路是错误的
N=6,珠子是4 1 1 4 1 1
一种合并方式是
(4 1 1) 4 1 1 = 4
4 1 (4 1 1) = 4
(4 1 4) 1 = 16
4) (4 1 = 16
4 4 = 64
总和是104,你的程序运算结果是56