• 中南林业大学校赛 I 背包问题 ( 折半枚举 || 01背包递归写法 )


    题目链接

    题意 : 中文题

    分析 : 

    价值和重量都太过于大,所以采用折半枚举的方法,详细可以看挑战的超大背包问题

    由于 n <= 30 那么可以不必直接记录状态来优化,面对每个用例

    直接采用递归回溯的方法来写这个 DP 即可

    #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
    ", DP(n, m));
        }
        return 0;
    }
    递归DP
    #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;
    }
    折半枚举
  • 相关阅读:
    javascript学习笔记1
    html的那些小小细节
    高级排序之希尔排序
    归并排序
    java 块语句 和引用类型
    扩展思维
    javase jdk 环境变量 涵义
    java 冒泡排序 二分查找 选择排序 插入排序
    kafka原理
    java web 程序---注册页面密码验证
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/9069722.html
Copyright © 2020-2023  润新知