zoukankan      html  css  js  c++  java
  • 砝码称重2

    【题目描述】

    有n个砝码,现要称一个质量为m的物体,询问最少需要挑出几个砝码来称,一个砝码最多只能挑一次。

    【输入描述】

    第一行输入两个整数n和m;

    接下来n行,每行输入一个整数表示砝码的重量。

    【输出描述】

    输出一个整数表示最少需要的砝码数。

    【样例输入】

    3 10

    5

    9

    1

    【样例输出】

    2

    【数据范围及提示】

    1 <= n <= 30,1 <= m <= 231,1 <= 每个砝码的质量 <= 230

    源代码:
    
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int m,n,L1=1,L2=1,Min=1000000000,i[31];
    struct Node
    {
        int Sum,Weight;
    }F1[400000],F2[400000]; //计算好情况数目,别想当然。
    int Rule(Node t1,Node t2)
    {
        return t1.Weight<t2.Weight;
    }
    void DFS1(int t,int S,int W) //t代表当前砝码编号,S代表已使用的砝码数量,W代表已使用的砝码总重。
    {
        if (t>(n>>1))
          return;
        F1[++L1].Sum=S+1;
        F1[L1].Weight=W+i[t];
        DFS1(t+1,S+1,W+i[t]); //取还是不取。
        DFS1(t+1,S,W);
    }
    void DFS2(int t,int S,int W) //同理于上。
    {
        if (t>n)
          return;
        F2[++L2].Sum=S+1;
        F2[L2].Weight=W+i[t];
        DFS2(t+1,S+1,W+i[t]);
        DFS2(t+1,S,W);
    }
    int Find(int t) //排序之后,二分查找。
    {
        int Left=0,Right=L2,Mid=L2>>1;
        while (Left<=Right)
        {
            if (F2[Mid].Weight>t)
            {
                Right=Mid-1;
                Mid=(Left+Right)>>1;
            }
            if (F2[Mid].Weight<t)
            {
                Left=Mid+1;
                Mid=(Left+Right)>>1;
            }
            if (F2[Mid].Weight==t)
              return Mid;
        }
        return -1;
    }
    int main() //然而并没有用到Hash。
    {
        scanf("%d%d",&n,&m);
        for (int a=1;a<=n;a++)
          scanf("%d",&i[a]);
        sort(i+1,i+n+1);
        DFS1(1,0,0);
        sort(F1+1,F1+L1+1,Rule);
        DFS2((n>>1)+1,0,0);
        sort(F2+1,F2+L2+1,Rule);
        for (int a=1;a<=L1;a++)
        {
            int t=Find(m-F1[a].Weight);
            if (t!=-1) //符合条件。
              Min=min(Min,F1[a].Sum+F2[t].Sum);
        }
        printf("%d",Min);
        return 0;
    }
    
    /*
        解题思路:
            本质上就是定义一个左根堆和一个右根堆,这样可以节省很多空间。之所以排序,是为了保证二分的正确性,然后进行查找匹配。
    */
  • 相关阅读:
    MyEclipse:详细使用教程
    JDK安装与配置详细图文教程
    windows下python3.6版本安装pygame
    windows下如何下载并安装Python
    python的 del 函数是删对象还是删引用
    python strip()函数的用法
    python的垃圾回收机制
    python中的sort方法
    python中del函数的垃圾回收
    两个数交换
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5903333.html
Copyright © 2011-2022 走看看