題意:
視窗可放n面紅藍白三種旗,規定同色不相鄰,藍在紅白之間。共有多少種放置方法。
思路:設dp[i][j]表示有i面旗,第i面旗填顏色j(j=01表示紅白)時的總數,第i面填j色時,i-1可以填1-j(紅白相間)或者藍色,兩種填法的計算:
(1)填1-j時有dp[i-1][1-j]種
(2)填藍色時i-2和i要填紅白色才能將i-1的藍色包圍,即i-2要填1-j,共dp[i-2][1-j]種
所以,狀態轉移方程為dp[i][j]=dp[i-1][1-j]+dp[i-2][1-j]。答案是dp[n][1]+dp[n][0]。
空間優化:
每一輪迴圈都要計算
dp[i][0] = dp[i-1][1]+dp[i-2][1]
dp[i][1] = dp[i-1][0]+dp[i-2][0]
兩式相加得:(dp[i][0] + dp[i][1]) = (dp[i-1][0]+ dp[i-1][1]) + (dp[i-2][0]+dp[i-2][1])
兩兩結構相同,去掉第二維,dp[i] 表示前i面旗的放置方法總數,第i面旗可以填紅白色。
由上面的方程得:dp[i] = dp[i-1] + dp[i-2]
直接給dp[i]分類很快,就是湊題解字數時,發現這種降維的方法,和揹包的降維不一樣。
狀態轉移分析:
第i面紅色,i-1面白色:dp[i-1]是i-1填紅白色的總數,紅白各一半,白色有dp[i-1]/2種
第i面紅色,i-1面藍色:i-2必須是白色,則有dp[i-2]/2種
第i面白色,i-1面紅色:同第一種,有dp[i-1]/2種
第i面白色,i-1面藍色:同第二種,有dp[i-2]/2種
四個加起來得到dp[i]。
初始化:
dp[i]依賴於前兩個,所以至少要提供兩個連續的dp[i],可以是dp[0] dp[1]或dp[1] dp[2]
演算法步驟:
步驟1:初始化為dp[i]=0,dp[1]=2
步驟2:遞推求dp[i],答案是dp[n]
演算法複雜度:
初始化和遞推都是乙個迴圈,時間複雜度o(n),空間複雜度o(n)
**:
#include constint max_n = 46
;long
long
intcnt[max_n];
intmain()
突然想到前面那個完全揹包的輸入,第i個物品用完就不用了,不用用陣列儲存。
這道題只要維護三個值dp[i] dp[i-1] dp[i-2]就可以了,也就是
c = a +b;b =a;
a = c; -> a+b未更新
就是a = a +b;
b = a – b; //
(a舊值+b)-b
維護兩個變數就行了ooo ,迴圈用while連for裡面的區域性變數也省了,**好短
演算法步驟見**,main函式四行,一行輸入,一行計算,一行輸出,一行return 0
**:
#include intn;long
long a=2,b=0; //
a=[1] b=a[0]
intmain()
1225 水王爭霸
水王爭霸 time limit 1000ms memory limit 65536k total submit 2 accepted 0 description 為了豐富校園網路生活,學校 bbs 舉行了一次水王爭霸賽。比賽開始後,選手們瘋狂灌水,都想爭取到水王這個榮譽稱號。但學校的 bbs 是如此...
1225 八數碼難題
時間限制 1 s 空間限制 128000 kb 題目等級 鑽石 diamond 題解檢視執行結果 description yours和zero在研究a 啟發式演算法.拿到一道經典的a 問題,但是他們不會做,請你幫他們.問題描述 在3 3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字。棋盤中留...
1225 八數碼難題
題目描述 description yours和zero在研究a 啟發式演算法.拿到一道經典的a 問題,但是他們不會做,請你幫他們.問題描述 在3 3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字。棋盤中留有乙個空格,空格用0來表示。空格周圍的棋子可以移到空格中。要求解的問題是 給出一種初始布...