zoukankan      html  css  js  c++  java
  • EOJ-2144 抗震机械制造

    http://acm.cs.ecnu.edu.cn/problem.php?problemid=2144

    题意:给出n种物品以及m种材料,每种物品由不同材料制成,每种材料需要一定的资金(付钱后可无限用),求资金不超过给定p的情况下能造出的最多种类物品

    题目用二进制的方式表示物品由哪些材料构成,1表示选,0表示不选,使用时转化为十进制,过程以二进制为主。

    思路:记下每个物品的材料状态(二进制转化为十进制)(a[i]),在资金不超过限定的条件下,选取包含给出物品材料状态的某种状态。假设某物品的材料状态为1010,则所有包含其状态的情况,都可以制造出该物品(如1110,1111,1011),即如果没有资金限制,11…11则是所有问题的最优解。

    dp[i][j]表示选择第i个物品时,选取材料状态为j时最多可以造出的物品数量,j从a[i] ~ 2^m-1 (只有大于等于a[i]的状态可能包含它)

    则当j状态是包含第i个物品状态a[i]时,dp[i][j]=dp[i-1][j]+1,(说明选取材料状态为j可制造出第i个物品,即是在取i-1个物品,材料状态为j时的最优解状态下加一),且j状态的资金不超过限定值。(可优化空间)

    j包含物品i的状态的表达式为 a[i] & j == a[i] ,例如1010 与1111 位与就是1010则包含, 而与1100位与变为了1000则不是包含。

     1 #include<map>
     2 #include<set>
     3 #include<list>
     4 #include<cmath>
     5 #include<ctime>
     6 #include<queue>
     7 #include<stack>
     8 #include<cctype>
     9 #include<cstdio>
    10 #include<string>
    11 #include<cstdlib>
    12 #include<cstring>
    13 #include<iostream>
    14 #include<algorithm>
    15 using namespace std;
    16 int c[20];                        //材料资金
    17 int getValue(int x){
    18     int sum=0,pos=0;
    19     while(x){
    20         sum+=(x%2)*c[pos++];
    21         x>>=1;
    22     }
    23     return sum;
    24 }
    25 int main(){
    26     int T;
    27     cin>>T;
    28     while(T--){
    29         int n,m,p;
    30         scanf("%d%d%d",&n,&m,&p);
    31         int a[105],dp[(1<<16)+5],k[(1<<16)+5];    //a[]为物品的材料状态,k[]存放每种状态的资金总和
    32         for(int i=0;i<m;i++)
    33             scanf("%d",c+i);
    34         for(int i=0;i<(1<<m);i++)
    35             k[i]=getValue(i);
    36         for(int i=1;i<=n;i++){
    37             int sum=0;
    38             for(int j=0;j<m;j++){
    39                 int x;
    40                 scanf("%d",&x);
    41                 sum+=pow(2.0,j)*x;
    42             }
    43             a[i]=sum;                //将材料状态存为十进制
    44         }
    45         memset(dp,0,sizeof(dp));
    46         for(int i=1;i<=n;i++)
    47             for(int j=(1<<m)-1;j>=a[i];j--){
    48                 if((j&(a[i]))==a[i] && k[j]<=p)        //表示j状态包含a[i]状态,且资金不大于限定值
    49                     dp[j]++;                        //在材料状态j下可存放第i个物品
    50             }
    51         int Max=0;
    52         for(int i=0;i<=(1<<m)-1;i++)
    53             Max=max(Max,dp[i]);                        //找到最优解(不一定在dp[(1<<m)-1]中,因为受资金限制)
    54         printf("%d
    ",Max);
    55     }
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    Ext.Net中,文件下载。
    Ext.Net中,DataView数据绑定之使用技巧。
    Ext.Net控件,简单案例1,让我们从Hello World开始,走进Ext.Net控件的世界!。
    VSCode入门设置成中文
    S2T40,第四章,简答4
    MongoDB学习笔记三:查询
    初等数论学习笔记一:整除的概念与带余除法
    MongoDB学习笔记四:索引
    初等数论学习笔记二:最大公因数与辗转相除法
    MongoDB学习笔记二:创建、更新及删除文档
  • 原文地址:https://www.cnblogs.com/KimKyeYu/p/3168580.html
Copyright © 2011-2022 走看看