• scau 1142 巡逻的士兵(分治)


    1142 巡逻的士兵

    时间限制:1000MS  内存限制:65536K
    提交次数:217 通过次数:58

    题型: 编程题   语言: G++;GCC

     

    Description

    有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。
    为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵, 
    或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现要求统计按这样的方法,
    总共可能有多少种不同的正好三个士兵去侦察的士兵组合方案。
    
    注: 按上法得到少于三士兵的情况不统计。
    
    1 <= N <= 2的32次方-1



    输入格式

    有多行,每行一个数字N,最后一行是0


    输出格式

    对每一行的数字N,输出针对N的方案数
    
    直到没有数字
    


     

    输入样例

    10
    4
    0
    


     

    输出样例

    2
    0
    
    
    
    
    
    
    
    
    
    
    
    
    *****************************************************************************************************************

    1.题意:将士兵分开,一直分到能游3个人一组的时候结束。

    2.解题方法:本题为用分治的方法,将一个很大的数分成很小的数。当一个数为偶数的时候,可以将它分解成两个相等不部分,即一边是奇数一边是偶数。但是当那个数是个奇数的时候可以分成n/2n-n/2(注:在int型变量省略小数,所以n/2==(n-1)/2)

    ****************************************************************************************************************

    具体例子分析:

                    20

                 |      |

                 10      10  

                |   |   |   |

                5   5   5   5

               | |  | |  | | | |

          2 3 2 3  2 3 2 3

    所以需要记录每一次分解左右的数,加起来就知道方案数

                       20(2+2)

                     |       |

                   10(1+1)     10(1+1)  

                  |    |      |    |

             5(1+0)  5(1+0)   5(1+0)  5(1+0)

               | |   | |     | |   | |

          2  3  2 3    2 3   2 3

    *************************************************************************************************

    要用上述的方法需要使用到函数的嵌套;

    #include <stdio.h>
    int select(unsigned n);
    int main()
    {
        unsigned n;<span style="font-family: Arial, Helvetica, sans-serif;">//n<2^32-1;用unsigned 可以防止溢出</span>
    
        while(scanf("%u",&n)!=EOF&&n)
        {
            printf("%d
    ",select(n));
        }
        return 0;
    }
    int select(unsigned n)
    {
        int left=0,right=0,sum=0;
        if(n==3)
            return 1;
        else if(n<3)
            return 0;
        else
        {
            if(n%2==0)//判断奇偶数
            {
                right=select(n/2);//右边的方案个数
                left=right;//偶数时,左右的方案个数相等
            }
            else
            {
                right=select(n/2);
                left=select(n-n/2);
            }
            sum=left+right;//计算总和
        }
        return sum;
    }
    

    虽然不是最快的方法,但是好理解一些
  • 相关阅读:
    hud 1397
    hdu 1211
    hdu 1124
    hdu 1104
    1788
    hdu 1796
    sdut 2169
    hdu 1019
    $http post 取不到数据
    sql
  • 原文地址:https://www.cnblogs.com/denghaiquan/p/6666090.html
Copyright © 2020-2023  润新知