zoukankan      html  css  js  c++  java
  • 51nod 1007正整数分组(01背包变形)

      题目大意就是给n个数,分2组,求2组和之差最小。

      这题我一开始写的dfs结果t了,后面看了题解说是0背包变形才恍然大悟。第一种解法:先把n个数的和sum求出来,要使得2组数和之差尽可能小,必定是要使得一组逼近sum/2,于是从这里入手,我们就转而求从n个数选若干个数,在和<=sum/2的情况下和能取得的最大值,这个时候就很明显了,这里把一个数的大小同时作为该数字的价值和体积,dp[i][j]表示从前i个数选若干个数放进容积为j的背包中能得到的最大价值,然后可以滚掉一维,最后答案就是dp[sum/2],表示从前n个数选若干个数,和不超过sum/2的情况下的最大和.

    看了其他大佬的博客还发现了第二种解法,定义f[i][j]为把前i个数分2组,差为j是否可行,状态转移有3种,详细见代码注释。这里就不能滚掉一维了,因为 第一种转移f[i][j]能从f[i-1][a[i]+j]转移过来。

    第一种解法

    #include<bits/stdc++.h>
    using namespace std;
    int dp[5005],a[105];
    int main()
    {
        int n,sum=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&(a[i])),sum+=a[i];
        for(int i=1;i<=n;i++)
            for(int j=sum/2;j>=a[i];j--)
                dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
        cout<<sum-dp[sum/2]-dp[sum/2]<<endl;
        return 0;
    
    }

    第二种解法

    #include<bits/stdc++.h>
    using namespace std;
    bool f[105][10000];
    int a[105];
    int main()
    {
        int n,sum=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&(a[i])),sum+=a[i];
        f[0][0]=1;
        for(int j=1;j<=sum;j++) f[0][j]=0;
        for(int i=1;i<=n;i++)
            for(int j=0;j<=sum;j++)
            {
                f[i][j]|=f[i-1][a[i]+j];//转移1,看成是把a[i]放入了和较小的那组,完了之后和较小的那组依然是和较小的那组
                if(j-a[i]>=0)
                    f[i][j]|=f[i-1][j-a[i]];//转移2,看成是把a[i]放入和较大的那组了,完了之和2组的差更大了
                if(a[i]-j>=0)
                    f[i][j]|=f[i-1][a[i]-j];//转移3,看成是把a[i]放入了和较小的那组,完了之后和较小的那组变成了和较大的那组
            }
        for(int j=0;j<=sum;j++)
            if(f[n][j])
            {
                cout<<j<<endl;
                return 0;
            }
    }
    
  • 相关阅读:
    类加载机制的学习4___类加载的过程
    类加载机制的学习3___自定义的类加载器
    类加载机制的学习2_____双亲委派模型
    使用.NET读取exchange邮件
    SSMS错误:A connection was successfully established with the server, but then an error occurred during the login process
    收缩数据库 DBCC SHRINKFILE
    How to: Change Sales Rep/Team via Mass Update
    Microsoft.Office.Interop.Word.Document.Open returns null on Windows Server 2008 R2
    设置文件夹的权限
    NetSuite API
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754817.html
Copyright © 2011-2022 走看看