• ZOJ--3631--Watashi's BG【枚举】


    链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4777

    题意:有n天,告诉你每天的花费,别人给你一笔资金m,你自己也有一部分资金(能够如果花不完),每天仅仅能花自己的钱或者花资金m中的钱,不能混着花,问m最多能花多少?


    思路:考虑到数据比較小,n最多仅仅有30,能够用枚举来做,枚举每天花m或者不花m,二进制枚举,复杂度2^30。这样复杂度要超时的,土豪说能够分两部分枚举,把结果存入两个数组,然后这两个数组结果再合并,复杂度n^2,这样二进制枚举最多是两个2^15,大大缩短了时间复杂度。

    后来我又用dfs写了一遍,果断T,看了别人的代码,有个剪枝非常关键,当前已使用的资金与全部还未使用的资金相加假设小于等于已得到的最大值,则剪枝。


    二进制枚举代码

    #include<cstring>
    #include<string>
    #include<fstream>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    #include<stack>
    #include<ctime>
    #include<cstdlib>
    #include<functional>
    #include<cmath>
    using namespace std;
    #define PI acos(-1.0)
    #define MAXN 5000100
    #define eps 1e-7
    #define INF 0x7FFFFFFF
    #define LLINF 0x7FFFFFFFFFFFFFFF
    #define seed 131
    #define MOD 1000000007
    #define ll long long
    #define ull unsigned ll
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    int a[200010],b[200010],va[40],vb[40];
    int main(){
        int i,j;
        int n,m;
        int la,lb,cnta,cntb,ans;
        while(scanf("%d%d",&n,&m)!=EOF){
            la = lb = cnta = cntb = ans = 0;
            for(i=0;i<n/2;i++){
                scanf("%d",&va[i]);
                la++;
            }
            for(i=n/2;i<n;i++){
                scanf("%d",&vb[i-n/2]);
                lb++;
            }
            int l = (1<<la);
            for(i=0;i<l;i++){
                int sum = 0;
                for(j=0;j<la;j++){
                    if(i&(1<<j)){
                        sum += va[j];
                    }
                }
                if(sum<=m){
                    a[cnta++] = sum;
                    ans = max(sum,ans);
                }
            }
            l = (1<<lb);
            for(i=0;i<l;i++){
                int sum = 0;
                for(j=0;j<lb;j++){
                    if(i&(1<<j)){
                        sum += vb[j];
                    }
                }
                if(sum<=m){
                    b[cntb++] = sum;
                    ans = max(sum,ans);
                }
            }
            sort(a,a+cnta);
            sort(b,b+cntb);
            if(ans==m){
                printf("%d
    ",ans);
                continue;
            }
            for(i=cnta-1;i>=0;i--){
                for(j=cntb-1;j>=0;j--){
                    if(a[i]+b[j]<=m){
                        ans = max(ans,a[i]+b[j]);
                        break;
                    }
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }


    DFS代码

    #include<cstring>
    #include<string>
    #include<fstream>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    #include<stack>
    #include<ctime>
    #include<cstdlib>
    #include<functional>
    #include<cmath>
    using namespace std;
    #define PI acos(-1.0)
    #define MAXN 5000100
    #define eps 1e-7
    #define INF 0x7FFFFFFF
    #define LLINF 0x7FFFFFFFFFFFFFFF
    #define seed 131
    #define MOD 1000000007
    #define ll long long
    #define ull unsigned ll
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    int a[40],jz[40];
    int n,m,maxm;
    void dfs(int step,int cnt){
        if(cnt>m)   return ;
        maxm = max(maxm,cnt);
        if(step<1) return ;
        if(cnt+jz[step]<=maxm)  return ;    //防TLE剪枝
        dfs(step-1,cnt);
        dfs(step-1,cnt+a[step]);
    }
    int main(){
        int i,j;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            jz[0] = 0;
            for(i=1;i<=n;i++)    jz[i] = jz[i-1] + a[i];
            maxm = 0;
            dfs(n,0);
            printf("%d
    ",maxm);
        }
        return 0;
    }
    
    


  • 相关阅读:
    MFC新建菜单项
    java连接mysql
    装visio 2007遇到了1706错误,解决办法
    Oracle协议适配器错误解决办法
    powershell 开启开发人员仪表盘
    sharepoint stsadm 创建网站脚本
    网站安全修复笔记1
    sharepoint ribbon添加菜单
    解决 由于代码已经过优化或者本机框架位于调用堆栈之上,无法计算表达式的值
    RDA实现SQL CE与SQL Server间数据存取
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3979731.html
Copyright © 2020-2023  润新知