中南林业大学校赛 I 背包问题 ( 折半枚举 || 01背包递归写法 )
题意 : 中文题
分析 :
价值和重量都太过于大,所以采用折半枚举的方法,详细可以看挑战的超大背包问题
由于 n <= 30 那么可以不必直接记录状态来优化,面对每个用例
直接采用递归回溯的方法来写这个 DP 即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define LL long long #define ULL unsigned long long #define scs(i) scanf("%s", i) #define sci(i) scanf("%d", &i) #define scd(i) scanf("%lf", &i) #define scl(i) scanf("%lld", &i) #define scIl(i) scanf("%I64d", &i) #define scii(i, j) scanf("%d %d", &i, &j) #define scdd(i, j) scanf("%lf %lf", &i, &j) #define scll(i, j) scanf("%lld %lld", &i, &j) #define scIll(i, j) scanf("%I64d %I64d", &i, &j) #define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k) #define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k) #define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k) #define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k) #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define lowbit(i) (i & (-i)) #define mem(i, j) memset(i, j, sizeof(i)) #define fir first #define sec second #define ins(i) insert(i) #define pb(i) push_back(i) #define pii pair<int, int> #define mk(i, j) make_pair(i, j) #define all(i) i.begin(), i.end() #define pll pair<long long, long long> using namespace std; int v[35]; int DP(int n, int m) { if(n < 0 || m < 0) return 0; if(n == 0 || m == 0) return 1; return DP(n-1, m-v[n]) + DP(n-1, m); } int main(void) { int n; while(~sci(n)){ int m; sci(m); for(int i=1; i<=n; i++) sci(v[i]); printf("%d\n", DP(n, m)); } return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define LL long long #define ULL unsigned long long #define scs(i) scanf("%s", i) #define sci(i) scanf("%d", &i) #define scd(i) scanf("%lf", &i) #define scl(i) scanf("%lld", &i) #define scIl(i) scanf("%I64d", &i) #define scii(i, j) scanf("%d %d", &i, &j) #define scdd(i, j) scanf("%lf %lf", &i, &j) #define scll(i, j) scanf("%lld %lld", &i, &j) #define scIll(i, j) scanf("%I64d %I64d", &i, &j) #define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k) #define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k) #define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k) #define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k) #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define lowbit(i) (i & (-i)) #define mem(i, j) memset(i, j, sizeof(i)) #define fir first #define sec second #define ins(i) insert(i) #define all(i) i.begin(), i.end() #define pb(i) push_back(i) #define pii pair<int, int> #define mk(i, j) make_pair(i, j) #define pll pair<long long, long long> using namespace std; const int maxn = 30 + 2; int n; LL m, v[maxn]; vector<LL> arr; int main(void) { while(cin>>n>>m){ arr.clear(); for(int i=0; i<n; i++) scl(v[i]); for(int i=0; i<(1<<(n/2)); i++){ LL sum = 0; for(int j=0; j<n/2; j++) if((i & (1<<j))) sum += v[j]; arr.pb(sum); } sort(all(arr)); int ans = 0; for(int i=0; i<(1<<(n-n/2)); i++){ LL sum = 0; for(int j=0; j<(n-n/2); j++) if((i & (1<<j))) sum += v[j+n/2]; ans += upper_bound(all(arr), m-sum) - arr.begin(); } cout<<ans<<endl; } return 0; }