Foreign 詠歎 模擬退火

2022-05-20 07:08:17 字數 2133 閱讀 7561

time limit: 100 sec  memory limit: 256 mb

有n根木棍,第i根長度為ai。你要貼著牆圍出乙個矩形區域,木棍圍成的矩形邊緣必須平行或垂直於牆,且又一邊必須利用牆。你可以把至多1根木棍劈成兩根(不一定要在整數字置)。最大化矩形面積。

包含多組資料。每組資料第一行乙個整數n,第二行n個整數ai。

輸出面積最大的矩形與牆壁平行的那條邊的長度(顯然是乙個整數),若有多個最優解輸出與牆壁平行的那條邊最長的。

33 3 3

44 4 4 468

對於10%的資料,n=2。

對於30%的資料,n<=15。

對於50%的資料,n<=32。

對於另外20%的資料,ai<=100。

對於100%的資料,2<=n<=40,1<=ai<=10^9,資料不超過10組。

首先,必然是全部木棍都用上的時候最優,對於n=2的時候,顯然就是分三種情況討論一下就好了。

然後我們從n=2的情況拓展。發現,其實可以把多個木棍並在一起,使其變為n=2的情況,然後討論。那麼現在答案只和兩段的長度有關了。

但是直接暴力搜尋是o(2^40)的,顯然不行,我們考慮分為兩部分來搜尋,搜尋前n/2個,和後n/2個,表示選不選得到的價值,現在效率是o(2*2^20)。

然後怎麼得到答案呢?顯然:如果我們設寬為x,則長為tot-2x(tot為總長),那麼這是乙個二次函式,必然有峰值。

所以我們大膽猜測,我們確定了一半,另外一半使得其答案最優的話也可能滿足有峰值的性質

然後我們固定一半,另一半運用模擬退火求解即可!

1 #include2 #include  

3 #include4 #include5 #include6 #include7 #include8 #include9

using

namespace

std;

10 typedef long

long

s64;

1112

const

int one = 2100000;13

14int

t,n;

15int a[45

],top1,top2;

16s64 stk1[one],stk2[one];

17s64 square, ans, tot, re;

1819

intget

() 20

2930

s64 get(s64 width,s64 length)

3138

39s64 check(s64 a,s64 b)

4048

49void dfs1(s64 val,int

t)50

52 dfs1(val,t+1); dfs1(val+a[t],t+1

);53}54

55void dfs2(s64 val,int

t)56

58 dfs2(val,t+1); dfs2(val+a[t],t+1

);59}60

61 s64 judge(int i,int

j)62

6566

double random()

67void deal(int

id)68

81 judge(now-1,id); judge(now+1

,id);82}

8384

void

solve2()

8598

99void dfs(s64 a,s64 b,int

t)100

106 dfs(a+a[t],b,t+1

);107 dfs(a,b+a[t],t+1

);108

}109

110void

solve1()

111117

118int

main()

119126 }

view code

模擬退火演算法

w 模擬退火演算法的基本思想 將乙個優化問題比擬成乙個金屬物體,將優化問題的目標函式比擬成物體的能量,問題的解比擬成物體的狀態,問題的最優解比擬成能量最低的狀態,然後模擬金屬物體的退火過程,從乙個足夠高的溫度開始,逐漸降低溫度,使物體分子從高能量狀態緩慢的過渡到低能量狀態,直至獲得能量最小的理想狀態...

模擬退火合集

首次接觸模擬退火 看來還是挺神奇的。主要參考這篇博文 題意判斷多邊形內部能否容納乙個半徑為r的圓,即在有限的平面內找最優範圍。遺傳演算法的結果難以掌控,爬山演算法又沒法保證跳出區域性最優,所以基於貪心原則的模擬退火演算法還是值得考慮的。然後就是設定每次變化的步長和演化方式。該題可以從每條邊的中點開始...

模擬退火演算法

一些求解極值的問題不能通過函式特性直接求解,只能暴力列舉,但是單純的列舉效率不高,通過模擬退火演算法可以高效的找到答案。學習好博文 最小圓覆蓋 hdu 3007 buried memory 大意 給出一些點,求出能覆蓋他們的最小的圓。輸出圓心和半徑 include include include i...