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