• POJ2923 状态压缩01背包 xingxing在努力


      这道题算是很经典的状态压缩01背包了, 题意是有一个人要用两辆小汽车搬家, 每辆小汽车都有一个最大载重量, 现在有一些要搬的家具, 告诉你这些家具的重量, 问最少几次能将这些家具搬完(每次两辆汽车必须出动, 即使有一辆车什么都没有装)? 物品个数不超过10,根据经验一般有10存在的话都要带点暴力的色彩, 那么这道题就是先要预处理所有一次搬走的家具的集合, 然后就将其转化成了01背包的问假设d[i][j]是前i个家具中搬走了j(集合)家具所需要的最少次数那么d[i][j] = min(d[i-1][j], d[i-1][k]) 其中k是j中去掉i集合的家具。这可以使用滚动数组优化一下。。wa点:1:judge函数的编写, 至今找不到我自己想的贪心判断法错那了   2:k的确定,其实这道题的实现应该是从d[i-1][k]推d[i][j],而不是d[i][j]求d[i-1][k].代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int inf = 0x3f3f3f3f;
    
    int Wu[1024+100];     //第i个物品的集合是Wu[i];
    int cnt;
    int n, c1, c2;
    int weight[20];
    
    int f[1024+100];
    
    /*int judge(int st)    //判断能否一次运走st集合的物品
    {
        int tpweight[15], numtp=0;
        for(int i=0; i<n; i++)
        {
            if((st&1) == 1)
                tpweight[numtp++] = weight[i];
            st >>= 1;
        }
        sort(tpweight, tpweight+numtp);
    
        int tpc1=c1, tpc2=c2;
        for(int i=0; i<2; i++)
        {
            int now = 0;
            while(now<numtp && tpc1-tpweight[now]>=0)
                tpc1 -= tpweight[now++];
            while(now<numtp && tpc2-tpweight[now]>=0)
                tpc2 -= tpweight[now++];
            if(now == numtp) return true;
            tpc1 = c2; tpc2 = c1;
        }
        return false;
    }
    */
    
    int vis[1100];
    
    bool judge(int st)           //判断两辆汽车能否一次将st集合中的物品运完    机智值得学习 然而为什么我的错了
    {
        memset(vis, 0, sizeof(vis));
        vis[0] = 1;
        int sum = 0;
        for(int i=0; i<n; i++) if(st&(1<<i))
        {
            sum += weight[i];
            for(int j=c1-weight[i]; j>=0; j--)
                if(vis[j]) vis[j+weight[i]] = 1;
        }
        for(int i=c1; i>=0; i--)
            if(vis[i] && sum-i<=c2) return true;
        return false;
    }
    
    int main()
    {
        int T, kase=0;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d%d%d", &n, &c1, &c2);
            for(int i=0; i<n; i++)
                scanf("%d", &weight[i]);
            cnt = 0;              //一共有cnt个物品
            for(int i=1; i<1<<(n); i++)
            {
                    if(judge(i))
                        Wu[cnt++] = i;
            }
            memset(f, 0x3f, sizeof(f));
            f[0] = 0;
            for(int i=0; i<cnt; i++)
                for(int j=(1<<n)-1; j>=0; j--)
                {
                    if(j|Wu[i] < (1<<n) && !(j&Wu[i]))     //物品i和j不应该有交集 其实不加也可以, 加上更加谨慎
                        f[j|Wu[i]] = min(f[j|Wu[i]], f[j]+1);
                }
            printf("Scenario #%d:
    ", ++kase);
            printf("%d
    
    ", f[(1<<n)-1]);
        }
        return 0;
    }
  • 相关阅读:
    Form组件
    LAMP+Varnish的实现
    缓存反向代理-Varnish
    CDN初识
    HTTP缓存初探
    Keepalived搭建主从架构、主主架构实例
    实现高可用-Keepalived
    nginx负载均衡实例
    lvs集群实现lvs-dr模型和lvs-nat模型
    LVS介绍
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5007696.html
Copyright © 2020-2023  润新知