「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」送礼物 解题报告的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python菜鸟爬虫技巧
- 下一篇: python+tensorflow CN