zoukankan      html  css  js  c++  java
  • 贪心砝码(分治法)

    被贪心和分治又虐了一天,还是太弱了..

    题目是这样的:有这样一个奇怪的天平,它的砝码只有1g, 3g, 9g, 27g......并且各只有一个,但它却能够称出所有整数g质量的物体例如要称出质量2g,那就一边放一个3g,另一边放物体和1g的砝码就可以了。放在物体那边的砝码在前面加负号表示之。

    有候选集合,需要求近似解或者最优解,这基本是贪心分治的标配,而核心思想就是根据候选集合不断的迭代问题的规模使其缩小,代码如下:

     1 #include "stdafx.h"
     2 #include<cstdlib>
     3 #include <stdio.h>
     4 #define Max 21
     5 //构造候选集合,自己做的时候已经被提示是贪心应用了,居然还是自己傻傻的算呢...真是天真
     6 unsigned int  Data[Max]={1,3,9,27,81,243,729,2187,6561,19683,59049,177147,531441,1594323,4782969,14348907,
     7 43046721,129140163,387420489,1162261467,3486784401 };
     8 //二分查找,确定子问题的解,当然这次用到了指针,虽然还不清楚指针有什么优劣,不过这次还是蛮好用的。
     9 unsigned int *Binary_Search(unsigned int  k)
    10 {
    11     int left = 0;
    12     int right = Max - 1;
    13     int middle;
    14     while(left <= right)
    15     {
    16         middle = (left + right) / 2;
    17         if(k > Data[middle])
    18             left = middle + 1;
    19         else if(k< Data[middle - 1])
    20             right = middle - 1;
    21         else 
    22             if(k >= Data[middle - 1] && k <= Data[middle])
    23             {
    24                 if( k == Data[middle - 1])
    25                         return &Data[middle - 1];
    26                 else
    27                         return &Data[middle];
    28             }
    29     }
    30     return &Data[middle];
    31 }
    32 //
    33 int k = -1;
    34 int mark = 0;
    35 //输入最终解,当然自身也是递归的对象
    36 void Print(unsigned int m)
    37 {
    38     unsigned int *i;
    39     i = Binary_Search(m);
    40     //迭代的最后一个子问题,输出结束本次运算
    41     if(*i == m)
    42     {
    43         printf("%u",m);
    44         return;
    45     }
    46     //在本题中,一个数如果大于等于3^n的一半,那么它的上界就是3^n,否则就是3^(n - 1),在这里用到了指针代替数组运算
    47     if(*i / 2 >=m)
    48         i = i -1;
    49     //辗转相减,不断的缩小目标值,k值则是加减号的标志(正为加,负为减)
    50     if(*i < m)
    51     {
    52         m = m - *i;
    53         k = 1;
    54     }
    55     //同上
    56     else
    57     {
    58         m = *i -m;
    59     }
    60     printf("%u",*i);
    61     //mark和k是控制辗转相减过程中符号的显示
    62     if(mark == 1)
    63         k = -k;
    64     //
    65     if(k == 1)
    66     {
    67         printf(" + ");
    68         mark = 0;
    69         k = -1;
    70     }
    71     //
    72     else
    73     {
    74         printf(" - ");
    75         mark = 1;
    76     }
    77     //递归迭代
    78     Print(m);
    79 }
    80 
    81 int _tmain(int argc, _TCHAR* argv[])
    82 {    
    83     unsigned int m;
    84     while(scanf("%d",&m) != EOF)
    85     {
    86         printf("%d = ",m);
    87         Print(m);
    88     }
    89     system("Pause");
    90     return 0;
    91 }

    总的来说,算是基本掌握了贪心分治的基础应用,这两天没有白虐,在一些细节上还有不熟练的地方,但是总算能给自己打个70分吧。

  • 相关阅读:
    安装Python及pip
    关于软件测试培训
    终于也为自己开了技术博客
    全球地址联动js包2021最新
    约瑟夫斯问题
    添加二级域名
    mysql导出数据
    mysql导入数据
    shopify
    MySQL数据库简介及常用命令
  • 原文地址:https://www.cnblogs.com/baikequanshu/p/3398261.html
Copyright © 2011-2022 走看看