題目描述
約翰有一架用來稱牛的體重的天平.與之配套的是N(1≤N≤1000)個已知品質的砝碼(所有砝碼品質的數值都在31位二進位內).每次稱牛時,他都把某頭奶牛安置在天平的某一邊,然後往天平另一邊加砝碼,直到天平平衡,於是此時砝碼的總品質就是牛的品質(約翰不能把砝碼放到奶牛的那邊,因為奶牛不喜歡稱體重,每當約翰把砝碼放到她的蹄子底下,她就會嘗試把砝碼踢到約翰臉上).天平能承受的物體的品質不是無限的,當天平某一邊物體的品質大於C(1≤C<2^30)時,天平就會被損壞. 砝碼按照它們品質的大小被排成一行.並且,這一行中從第3個砝碼開始,每個砝碼的品質至少等於前面兩個砝碼(也就是品質比它小的砝碼中品質最大的兩個)的品質的和. 約翰想知道,用他所擁有的這些砝碼以及這架天平,能稱出的品質最大是多少.由於天平的最大承重能力為C.他不能把所有砝碼都放到天平上.
現在約翰告訴你每個砝碼的品質,以及天平能承受的最大品質.你的任務是選出一些砝碼,
使它們的品質和在不壓壞天平的前提下是所有組合中最大的. 搜尋
因為權值在int內,那麼按照斐波那契40多項就會爆。
因此n<=40。
我們考慮搜尋咯。
枚舉每個選不選,這樣跑不過。
可以考慮加可行性減枝(或者叫最優性減枝。),如果剩餘數全選還是不比當前答案大那就退了吧。
為了讓這個減枝發揮效果,當然要倒著搜啦。
#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;typedef long long ll;int a[1500];ll sum[1500];int i,j,k,l,t,n,m,ans;void dfs(int x,int y){ if (y>m) return; ans=max(ans,y); if (!x) return; if (y+sum[x]<=ans) return; dfs(x-1,y+a[x]); dfs(x-1,y);}int main(){ scanf("%d%d",&n,&m); fo(i,1,n) scanf("%d",&a[i]); fo(i,1,n) sum[i]=sum[i-1]+a[i]; /*fd(i,n,1) if (ans<=m-a[i]) ans+=a[i];*/ dfs(n,0); printf("%d\n",ans);}