日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Uva12325 Zombie's Treasure Chest [二分区间+模拟退火]

發布時間:2023/12/3 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Uva12325 Zombie's Treasure Chest [二分区间+模拟退火] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Zombie’s Treasure Chest

題目鏈接

https://cn.vjudge.net/problem/UVA-12325

題意

兩種物品無窮多個,第一種物品重量s1s_1s1?,價值v1v_1v1?,第二種物品重量s2s_2s2?,價值v2v_2v2?,背包重nnn,求能裝的最大價值之和. 數據全都是2e92e92e9.也就是兩種物品的完全背包.

題解

不可思議吧,這題還能模擬退火?

但仔細一想,求解最優值,而且隨機解的生成也很簡單,當然可以嗎,模擬退火搞啦.

模擬退火的板子可以到我以前的博客里找到,現在默認大家都知道模擬退火怎么寫了.

這道題我雖然用模擬退火AAA掉了,但也嘗試了好多發,現在把我采坑的過程根大家分享一下.

嘗試一

直接套板子,設xxx為第一種物品取的個數,顯然x∈[0,?ns1?]x \in [0,\lfloor \frac{n}{s_1} \rfloor]x[0,?s1?n??],那么第二種物品的個數就是y=?n?s1?v1s2?y =\lfloor \frac{n-s_1*v_1}{s_2} \rfloory=?s2?n?s1??v1???.

因此模擬退火的時候我可以在區間[0,?ns1?][0,\lfloor \frac{n}{s_1} \rfloor][0,?s1?n??]中隨機一個數作為xxx,然后計算yyy,并且計算能量值E=x?v1+y?v2E = x*v_1+y*v_2E=x?v1?+y?v2?.

最后調調參數,使得平衡一下答案精度和時間復雜度.

嘗試結果

多次嘗試以后,一直WA,自己造了組極端數據2000000000,2,3,1,12000000000,2,3,1,12000000000,2,3,1,1,發現根本過不去,總結原因:當隨機區間過大的時候,很難隨機到正確解,所以算法就在某個半山腰停住了.

嘗試二

要想能想要枚舉到最優解,區間一定不能太大.我們可以分塊進行模擬退火,這樣可以保證每次隨機的區間不會太大,區間上的某一個點被隨機到的概率就更大了,這種做法我還沒有試過,但是感覺應該可行.我們進一步發現,這個函數的峰不會太多(實際沒幾個)大致是具有單調性質的,因此我們采用二分區間的做法,即對于當前區間,用模擬退火算出一個最優解,然后用這個解與區間中點做比較從而確定下一個需要進行模擬退火的區間.

通過多次調參之后:

代碼

#include <iostream> #include <algorithm> #include <cmath> #include <ctime> #include <cstring> int T,cas; long long n,s1,v1,s2,v2; double randfloat() {return rand()/(RAND_MAX+0.0); } void solve() {std::cin >> n >> s1 >> v1 >> s2 >> v2;long long ansE = 0,ansx = 0;long long nowE = 0,x = 0;long long low = 0,up = n/s1;for(int cc = 1;cc <= 20;++cc) {double T0 = 1000000,Tk = 1,T = T0,d = 0.999;while(T > Tk) {long long newx = low + rand()%(up-low+1);long long newE = newx * v1 + ((n-newx*s1)/s2)*v2;if(newE < nowE || randfloat() > exp((nowE-newE)/T)) {nowE = newE;x = newx;}T *= d;if(newE > ansE) {ansE = newE;ansx = newx;}}long long mid = (low + up)/2;if(ansx > mid) low = mid;else up = mid;}std::cout << "Case #" << ++cas << ": " << ansE << std::endl; } int main() {std::ios::sync_with_stdio(false);std::cin >> T;while(T--) solve();return 0; }

總結

以上是生活随笔為你收集整理的Uva12325 Zombie's Treasure Chest [二分区间+模拟退火]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。