zoukankan      html  css  js  c++  java
  • 【DP合集】m-knapsack

    给出 n 个物品,第 i 个物品有重量 w i 。现在有 m 个背包,第 i 个背包的限重为 c i ,求最少用几个背 包能装下所有的物品。

    Input

    输入的第一行两个整数 n, m ( n ≤ 24 , m ≤ 100) 。 
    接下来一行 n 个整数,描述 w ( w i ≤ 10^8 ) 。 
    接下来一行 m 个整数,描述 c ( c i ≤ 10^8 ) 。

    Output

    输出一行一个整数,描述最少需要使用的背包数。如果没有可行的方案来装下所有物品,请输出”NIE” (不含引号)。

    题解:O(∩_∩)O谢谢出这套题目的学长,题目出的很好,好了,对于这个题目,因为我们要选择几个信息或者说记住几个特征,既可以描述所以的状态又方便转移,显然这个题状态很直接,我们显然要记住这个序列的所有物品是否被选,还要记住,当前用了几个背包,
    还要知道当前的背包还剩多少,所有可以状压一个2进制数i表示那些物品是否被选,设dp[i]表示要装下i最少要多少个背包,然后rest[i]
    表示用了dp[i]个背包后还有一部分剩下的重物放在第dp[i]+1个背包的重量,那么转移就是显然的了。注意我是用记忆化搜索,如果dp[i]<n说明这个状态已经算过了,就可以直接返回了。
     
    代码:
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    short dp[16777217];int use[16777217];
    int wu[110],bao[110],n,m,inf;
     
    void cl(){
        memset(wu,0,sizeof(wu));
        memset(bao,0,sizeof(bao));
        memset(dp,127,sizeof(dp));
        memset(use,127,sizeof(use));
        inf=use[0];
    }
     
    bool comp(int x,int y){
        if(x>y) return 1;
        return 0;
    }
     
    void dfs(int x){
        if(dp[x]<n) return;
        int q=inf,p=inf;
        for(int now=1;now<=n;now++){
            if(x&(1<<(now-1))){
                int r=x-(1<<(now-1));
                dfs(r);
                if(bao[dp[r]+1]-use[r]>=wu[now]) q=dp[r],p=use[r]+wu[now];
                else if(bao[dp[r]+1]>=wu[now]&&bao[dp[r]+2]>=wu[now]) q=dp[r]+1,p=wu[now];
                else continue;
                if(q<dp[x]) dp[x]=q,use[x]=p;
                else if(q==dp[x]&&p<use[x]) use[x]=p;
            }
        }
    }
     
    int main(){
        cl();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&wu[i]);
        for(int i=1;i<=m;i++) scanf("%d",&bao[i]);
        sort(wu+1,wu+n+1,comp);
        sort(bao+1,bao+m+1,comp);
        if(bao[1]<wu[1]) {printf("NIE");return 0;}
        dp[0]=use[0]=0;
        dfs((1<<n)-1);
        if(dp[(1<<n)-1]>m) printf("NIE");
        else printf("%d",dp[(1<<n)-1]+(use[(1<<n)-1]>0));
        return 0;
    }
  • 相关阅读:
    drf 之 JWT认证 什么是集群以及分布式 什么是正向代理,什么是反向代理
    drf 之自定制过滤器 分页器(三种)如何使用(重点) 全局异常 封装Response对象 自动生成接口文档
    课堂练习之“寻找最长单词链”
    《人月神话》读书笔记(三)
    用户体验
    第十四周进度报告
    课堂练习之“寻找水王”
    《人月神话》读书笔记(二)
    第二阶段冲刺(十)
    第二阶段冲刺(九)
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7198128.html
Copyright © 2011-2022 走看看