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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

「CH2401」送礼物 解题报告

發布時間:2024/1/8 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「CH2401」送礼物 解题报告 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

CH2401 送禮物

描述

作為懲罰,GY被遣送去幫助某神牛給女生送禮物(GY:貌似是個好差事)但是在GY看到禮物之后,他就不這么認為了。某神牛有N個禮物,且異常沉重,但是GY的力氣也異常的大(-_-b),他一次可以搬動重量和在w(w<=2^31-1)以下的任意多個物品。GY希望一次搬掉盡量重的一些物品,請你告訴他在他的力氣范圍內一次性能搬動的最大重量是多少。

輸入格式

第一行兩個整數,分別代表W和N。
以后N行,每行一個正整數表示G[i],G[i]<= 2^31-1。

輸出格式

僅一個整數,表示GY在他的力氣范圍內一次性能搬動的最大重量。

樣例輸入

20 5 7 5 4 18 1

樣例輸出

19

數據范圍與約定

  • 對于20%的數據 N<=26
    對于40%的數據 W<=2^26
    對于100%的數據 N<=45 W<=2^31-1

思路

這么小的數據。。。一般是搜索吧???這么大的W,用DP做肯定不成,而且也不資瓷離散化。。。。

直接搜?+剪枝?我已經剪不下去了。。。不過80分勉勉強強還可以~

代碼(搜索+剪枝)

#include<bits/stdc++.h> using namespace std; #define LL long long #define MAXN 50int N; LL W, ans; LL G[MAXN], f[MAXN];//f表示“后綴和”bool cmp( LL x, LL y ){ return x > y; }void DFS( int x, LL h ){//x表示當前搜的是第x件物品,h表示已經取到的總重量while( x <= N && h + G[x] > W ) x++;//由于是降序排序,找到第一個還能繼續搬的物品if ( x > N ){ ans = max( ans, h ); return; }//沒東西了(或者沒有可以搬的了),當然得回溯for ( ; x <= N; ++x ){if ( h + f[x] <= W ){ ans = max( ans, h + f[x] ); return; }//剪枝~ 后面都能拿,當然要都拿來最優啦~ 這個剪枝可以看做是最優化剪枝DFS( x + 1, h + G[x] );} }int main(){scanf( "%lld%d", &W, &N );for ( int i = 1; i <= N; ++i ) scanf( "%lld", &G[i] );sort( G + 1, G + N + 1, cmp );//剪枝~ 降序排序再搜~for ( int i = N; i >= 1; --i ) f[i] = f[i + 1] + G[i];DFS( 1, 0 );printf( "%lld\n", ans );return 0; }

相信大家都不會僅滿足于80分~還有倆測試點呢。。。
我們用一種神奇的搜索方式——雙向搜索!

也就是說,先找前半段,預處理出所有可以達到的總重量,存在一個數組F中,然后再搜索后半段,對于后半段已取的質量,在F中二分找出既滿足條件,又最大的重量,加起來更新ans的值就可以了。這樣復雜度就為O(\(2^{\frac n 2 }+2^{\frac n 2 } \times \log_2n\))基本可以滿足要求。

代碼

#include<bits/stdc++.h> using namespace std; #define LL long long #define MAXN 50int N, M; LL W, ans; LL G[MAXN]; LL F[20000000], tot;bool cmp( LL x, LL y ){ return x > y; }void DFS_1( int x, LL h ){//第一次搜索,注意所有能得到的重量都要記錄,所以不必剪枝 還有注意0也要記錄F[++tot] = h;while( x <= M && h + G[x] > W ) x++;for ( ; x <= M; ++x ) DFS_1( x + 1, h + G[x] ); }int EF( LL x ){//手打二分~int l(1), r(tot), mid, ans(1);while( l <= r ){mid = ( l + r ) >> 1;if ( F[mid] + x <= W ) l = mid + 1, ans = mid;else r = mid - 1;}return ans; }void DFS_2( int x, LL h ){ans = max( ans, h + F[EF(h)] );while( x <= N && h + G[x] > W ) x++;for ( ; x <= N; ++x ) DFS_2( x + 1, h + G[x] ); }int main(){scanf( "%lld%d", &W, &N ); M = ( N >> 1 ) + 2;//lyd大佬說前半段1~N/2+2最快~蒟蒻當然照做for ( int i = 1; i <= N; ++i ) scanf( "%lld", &G[i] );sort( G + 1, G + N + 1, cmp );//照樣排序DFS_1( 1, 0 );sort( F + 1, F + tot + 1 ); tot = unique( F + 1, F + tot + 1 ) - F - 1;//排序&去重DFS_2( M + 1, 0 );printf( "%lld\n", ans );return 0; }

搜索真是博大精深~

轉載于:https://www.cnblogs.com/louhancheng/p/10099459.html

總結

以上是生活随笔為你收集整理的「CH2401」送礼物 解题报告的全部內容,希望文章能夠幫你解決所遇到的問題。

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