zoukankan      html  css  js  c++  java
  • hdu1059(多重背包优化)

    使用一种二进制的优化, 可以完美的解决这题,《背包九讲》中说的非常好

    但是还有一种线性复杂的算法。 应该算是该题很巧妙的解法

    for(i=1;i<=6;i++)  
            {  
                for(l=total;l>=0;l--)  
                {  
                    if(dp[l]==0)    continue;  
                    for(k=1;k<=num[i]&&k*i+l<=total;k++)    
                    {  
                        if(dp[k*i+l])   break;  // 这个剪枝瞬间将复杂度从N^2变成了N。 
                        dp[k*i+l]=1;  
                    }  
                }  
            }  

    代码中total是我们要装满的容量, 循环的次序很重要。 当关键还是那一步剪枝

    在附上一份用二进制优化多重背包的代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    #include <map>
    #include <queue>
    #include <sstream>
    #include <iostream>
    using namespace std;
    #define INF 0x3fffffff
    struct node
    {
        int w,c;
    }g[10010]; //将log2压缩后的元素存在这里!
    
    int k[10];
    int dp[2002000];
    
    int mpow(int x)
    {
        int sum=1;
        for(int i=0;i<x;i++)
            sum=sum*2;
        return sum;
    }
    
    int main()
    {
        //freopen("//home//chen//Desktop//ACM//in.text","r",stdin);
        //freopen("//home//chen//Desktop//ACM//out.text","w",stdout);
        int tt=1;
        while(1)
        {
            int tmp=0,sum=0;
            for(int i=1;i<=6;i++)
            {
                scanf("%d",&k[i]);
                tmp+=k[i];
                sum+=k[i]*i;
            }
            if(tmp==0) break;
            printf("Collection #%d:
    ",tt++);
            if(sum%2!=0)
            {
                printf("Can't be divided.
    ");
                printf("
    ");
                continue;
            }
            int cnt=0;
            for(int i=1;i<=6;i++)
            {
                if(k[i]==0) continue;
                tmp=0;
                int tk=1;
                while(2*tk-1 < k[i])
                {
                    g[cnt].w=1;
                    g[cnt].c=i*tk;
                    cnt++;
                    tmp+=tk;
                    tk*=2;
                }
                g[cnt].w=1;
                g[cnt].c=i*(k[i]-tmp);
                cnt++;
            }
            for(int i=1;i<=sum/2;i++)
            {
                dp[i]=-INF;
            }
            dp[0]=0;
            for(int i=0;i<cnt;i++)
            {
                for(int j=sum/2;j>=g[i].c;j--)
                {
                    dp[j]=max(dp[j],dp[j-g[i].c]+g[i].w);
                }
            }
            if(dp[sum/2]>=0)
                printf("Can be divided.
    ");
            else printf("Can't be divided.
    ");
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    flask 指定前端文件路径以及静态文件路径
    pycharm git修改密码
    Web应用搭建
    python学习
    python解析jSON文件
    通过DLNA将电脑视频投射到电视屏幕
    U盘自动复制文件
    kali PIN码破解
    mdk3洪水攻击教程
    sqlmap(网站数据库注入)
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/3166816.html
Copyright © 2011-2022 走看看