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;
    }
  • 相关阅读:
    LUA 协程
    LUA GC 简单测试
    软件重构-笔记
    托管执行过程
    文件夹 加密
    db 文件 查看 打开 工具 db 中文 版 navicat 中文
    qq sid qq sid 是什么 qq sid 怎么用
    windows系统,联系人文件。个性化。
    csdn 音乐 怎么拦截 提交后的程序 csdn 栏目 音乐 csdn 添加 音乐
    CSDN博客栏目设置个性化
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/3166816.html
Copyright © 2011-2022 走看看