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;
    }
    
    /*
        解题思路:
            本质上就是定义一个左根堆和一个右根堆,这样可以节省很多空间。之所以排序,是为了保证二分的正确性,然后进行查找匹配。
    */
  • 相关阅读:
    线程同步之条件变量使用手记
    如何实现文件增量同步——算法
    javascript 复习笔记
    cocos2dx 多图层点击事件及管理相关问题记录
    cocos2dx 2.1.1 jsbinding 游戏帧数下降问题记录
    cocos2dx jsb + cocosbuilder 编译到安卓下问题处理(待续)
    cocos2dxjsb及Cocosbuilder使用相关问题处理记录
    cocos2dx jsb 的本地存储
    cocos2dxjsb 跨语言调用及第三方集成 过程记录
    cocos2dx 2.1.1 升级2.1.3版本 记录
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5903333.html
Copyright © 2011-2022 走看看