• 砝码称重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;
    }
    
    /*
        解题思路:
            本质上就是定义一个左根堆和一个右根堆,这样可以节省很多空间。之所以排序,是为了保证二分的正确性,然后进行查找匹配。
    */
  • 相关阅读:
    递归 深拷贝
    js 基础复习(0)
    js数组冒泡排序,快速排序的原理以及实现
    .sass 和 .scss 区别
    ionic2-从搭建环境说起
    Unity3d截图保存到Android相册的实现
    总是要总结一年的工作(写给自己和想要从技术创业开公司的朋友们)
    初入职场(插曲-如何更称职的工作)
    初入职场(插曲-你的成长代价)
    初入职场(面试)
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5903333.html
Copyright © 2020-2023  润新知