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 #includeview code3 #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 }
模擬退火演算法
w 模擬退火演算法的基本思想 將乙個優化問題比擬成乙個金屬物體,將優化問題的目標函式比擬成物體的能量,問題的解比擬成物體的狀態,問題的最優解比擬成能量最低的狀態,然後模擬金屬物體的退火過程,從乙個足夠高的溫度開始,逐漸降低溫度,使物體分子從高能量狀態緩慢的過渡到低能量狀態,直至獲得能量最小的理想狀態...
模擬退火合集
首次接觸模擬退火 看來還是挺神奇的。主要參考這篇博文 題意判斷多邊形內部能否容納乙個半徑為r的圓,即在有限的平面內找最優範圍。遺傳演算法的結果難以掌控,爬山演算法又沒法保證跳出區域性最優,所以基於貪心原則的模擬退火演算法還是值得考慮的。然後就是設定每次變化的步長和演化方式。該題可以從每條邊的中點開始...
模擬退火演算法
一些求解極值的問題不能通過函式特性直接求解,只能暴力列舉,但是單純的列舉效率不高,通過模擬退火演算法可以高效的找到答案。學習好博文 最小圓覆蓋 hdu 3007 buried memory 大意 給出一些點,求出能覆蓋他們的最小的圓。輸出圓心和半徑 include include include i...