• 基础背包(一)


    hdu 2602 01背包

    许多年前,在泰迪的家乡,有一个人被称为“骨收藏家”。这个人喜欢收集各种各样的骨头,比如狗的,牛的,他也去了坟墓

    采骨者有一个体积为v的大袋子,在他的采集过程中有很多骨头,很明显,不同的骨头有不同的价值和体积,现在考虑到每一块骨头的价值,你能计算出采骨者能得到的总价值的最大值吗

    输入

    第一行包含整数t,即事例数。

    接下来是t例,每例三行,第一行包含两个整数n,v,(n<=1000,v<=1000),表示骨骼数量和他的包的体积。第二行包含n个整数,表示每个骨骼的值。第三行包含n个整数,表示每个骨骼的体积。

    产量 

    每行一个整数,表示总值的最大值(此数字将小于2 31)。

    解题思路:简单01背包

    一维解法:

    #include<iostream>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=1100;
    int n,V,dp[maxn],weight[maxn],value[maxn],num[maxn];
    int main(){
        int t;
        cin>>t;
        while(t--){
            cin>>n>>V;
            for(int i=1;i<=n;i++)cin>>value[i];
            for(int i=1;i<=n;i++)cin>>weight[i];
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++){
                for(int j=V;j>=weight[i];j--)
                    dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
            }
            cout<<dp[V]<<endl;
        }
        return 0;
    }

    二维解法:

    #include<iostream>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=1100;
    int n,V,dp[maxn][maxn],weight[maxn],value[maxn],num[maxn];
    
    int main(){
        int t;
        cin>>t;
        while(t--){
            cin>>n>>V;
            for(int i=1;i<=n;i++)cin>>value[i];
            for(int i=1;i<=n;i++)cin>>weight[i];
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++){
                for(int j=0;j<=V;j++){
                    if(j>=weight[i])dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
                    else dp[i][j]=dp[i-1][j];
                }
            }
            cout<<dp[n][V]<<endl;
        }
        return 0;
    }

    hdu 1114  完全背包

    题目大意:

    输入空的存钱罐的重量以及满了的重量
    输入硬币种类数t
    以下t行输入t种硬币每个硬币的重量以及面值
    求此情况下该存钱罐至少能存的钱数,无解就输出无解
     
    解题思路:完全背包问题,注意初始化,初始化为无穷大表示不合法,如果计算最后还是无穷大则表示无解,把max改成min就好了
    一维解法:
    #include<iostream>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=11000;
    int n,V,dp[maxn],weight[maxn],value[maxn],num[maxn];
    
    int main(){
        int t;
        cin>>t;
        while(t--){
            int v1,v2;
            cin>>v1>>v2;
            V=v2-v1;
            cin>>n;
            for(int i=1;i<=n;i++)cin>>value[i]>>weight[i];
            memset(dp,0x3f,sizeof(dp));
            dp[0]=0;
            for(int i=1;i<=n;i++)
                for(int j=weight[i];j<=V;j++)
                    dp[j]=min(dp[j],dp[j-weight[i]]+value[i]);
            if(dp[V]==0x3f3f3f3f)puts("This is impossible.");
            else printf("The minimum amount of money in the piggy-bank is %d.
    ",dp[V]);
        }
        return 0;
    }

    二维解法:

    #include<iostream>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=11000;
    int n,V,dp[505][maxn],weight[maxn],value[maxn],num[maxn];
    
    int main(){
        int t;
        cin>>t;
        while(t--){
            int v1,v2;
            cin>>v1>>v2;
            V=v2-v1;
            cin>>n;
            for(int i=1;i<=n;i++)cin>>value[i]>>weight[i];
            memset(dp,0x3f,sizeof(dp));
            for(int i=0;i<=n;i++)dp[i][0]=0;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=V;j++){
                    if(j>=weight[i]) dp[i][j]=min(dp[i-1][j],dp[i][j-weight[i]]+value[i]);
                    else dp[i][j]=dp[i-1][j];
                }
            }
            if(dp[n][V]==0x3f3f3f3f)puts("This is impossible.");
            else printf("The minimum amount of money in the piggy-bank is %d.
    ",dp[n][V]);
        }
        return 0;
    }

    hdu 1171 多重背包

    题目大意:给你n个物品的价值和物品的数量,如何分使得A,B所得价值最接近并且A的价值不能小于B

    解题思路:完全背包,背包的容量为价值的总和的一半

    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int maxn=110000;
    int n,V,dp[55][maxn],weight[maxn],value[maxn],num[maxn];
    int main(){
        while(cin>>n){
            if(n<0)break;
            int sum=0;
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++){
                cin>>value[i]>>num[i];
                weight[i]=value[i];
                sum+=value[i]*num[i];
            }
            V=sum/2;
            if(sum%2)V++;
            for(int i=1;i<=n;i++)
                for(int j=0;j<=num[i];j++)
                    for(int k=V;k>=j*weight[i];k--)
                        dp[i][k]=max(dp[i-1][k],dp[i-1][k-j*weight[i]]+j*value[i]);
            cout<<max(dp[n][V],sum-dp[n][V])<<" "<<min(dp[n][V],sum-dp[n][V])<<endl;
        }
        return 0;
    }

    hdu 2844 多重背包+二进制优化

    题目大意:给出n种硬币的价值以及数目,求这n种硬币可以在1-m中可以支付的价格有多少种

    解题思路:硬币的价值同时也是硬币的代价,dp[j]表示容量为j的背包所可以得到的最大价值,如果等于j表示可以支付价钱j

    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int maxn=110000;
    int n,m,V,dp[maxn],value[maxn],num[maxn],vis[maxn],weight[maxn];
    int main(){
        while(cin>>n>>m){
            if(n==0&&m==0)break;
            for(int i=1;i<=n;i++) cin>>value[i];
            for(int i=1;i<=n;i++) cin>>num[i];
            int ans=0;
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++){
                if(value[i]*num[i]>m){
                    for(int j=value[i];j<=m;j++)  //完全背包 
                        dp[j]=max(dp[j],dp[j-value[i]]+value[i]);
                }else{
                    //二进制优化01背包 
                    for(int j=1;j<=num[i];j*=2){
                        for(int k=m;k>=j*value[i];k--)
                            dp[k]=max(dp[k],dp[k-j*value[i]]+j*value[i]);
                        num[i]-=j;
                    }
                    if(num[i]){
                        for(int k=m;k>=num[i]*value[i];k--)
                            dp[k]=max(dp[k],dp[k-num[i]*value[i]]+num[i]*value[i]);
                    }
                }
            }
            for(int i=1;i<=m;i++)
            if(dp[i]==i)ans++;
            cout<<ans<<endl;        
        }
        return 0;
    }

    hdu 1059 多重背包+二进制优化

    题目大意:给你6种不同价值的硬币的数量,价值分别是1~6,问你能否可以将这些硬币分成两堆,每堆的价值一样。

    解题思路:和hdu1171很像,把价值总和的一半看成背包容量,计算形成最大的价值是否可以达到价值总和的一半

    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int maxn=110000;
    int n,V,dp[maxn],value[maxn],num[maxn],vis[maxn],weight[maxn];
    int main(){
        int T=0;
        while(cin>>num[1]>>num[2]>>num[3]>>num[4]>>num[5]>>num[6]){
            int sum=0;
            n=6;
            T++;
            for(int i=1;i<=6;i++)sum+=num[i];
            if(sum==0)break;
            sum=0;
            for(int i=1;i<=6;i++){
                value[i]=i;
                sum+=value[i]*num[i];
            }
            printf("Collection #%d:
    ",T);
            if(sum%2){
                puts("Can't be divided.");
                puts("");
                continue;
            }
            V=sum/2;
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++){
                if(value[i]*num[i]>V){
                    for(int j=value[i];j<=V;j++)  //完全背包 
                        dp[j]=max(dp[j],dp[j-value[i]]+value[i]);
                }else{
                    //二进制优化 
                    for(int j=1;j<=num[i];j*=2){
                        for(int k=V;k>=j*value[i];k--)
                            dp[k]=max(dp[k],dp[k-j*value[i]]+j*value[i]);
                        num[i]-=j;
                    }
                    if(num[i]){
                        for(int k=V;k>=num[i]*value[i];k--)
                            dp[k]=max(dp[k],dp[k-num[i]*value[i]]+num[i]*value[i]);
                    }
                }
            }
            if(dp[V]==V) puts("Can be divided.");
            else puts("Can't be divided.");
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    9.1: 请每个小组在 cnblogs.com 上面创建团队博客,第一个博客把小组成员都介绍一下 #团队博客作业1------------------答题者:徐潇瑞
    5.你所在的学校有计算机科学专业和软件工程专业么?相关专业的教学计划和毕业出路有什么不同?阅读有关软件工程和计算机科学的区别的文章,谈谈你的看法。
    11. 请问 “软件” 和 “软件工程” 这些词汇是如何出现的
    7.有人认为,“中文编程”是解决中国程序员编程效率一个秘密武器,请问它是一个 “银弹” 么?
    6.有学生提到,在大学选课的时候,可以写一个“刷课机”的程序,利用学校选课系统的弱点或漏洞,帮助某些人选到某些课程。或者帮助用户刷购票网站,先买到火车票。这些软件合法么?符合道德规范么?是在“软件工程”的研究范围么?——回答者:张立鹏
    3. 上网调查一下目前流行的源程序版本管理软件和项目管理软件都有哪些, 各有什么优缺点? (提示:搜索一下Microsoft TFS、GitHub、Trac、Bugzilla、Rationale,Apple XCode),请用一个实际的源代码管理工具来建立源代码仓库,并签入/签出代码。
    现代软件工程 第一章 【概论】第3题——张晓丽
    右值引用、移动语义
    客车网上售票系统--需求分析
    2019JS必看面试题
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/10651433.html
Copyright © 2020-2023  润新知