zoukankan      html  css  js  c++  java
  • 2017-9-16C#笔记(枚举算法,百元买鸡)

    1. 枚举算法:

    百元买鸡

    枚举算法的Ì例子:问题如下:某3人有100元打算买100只鸡,其中公鸡为5元每只,母鸡为3元每只,小?鸡为3只1块钱,问可以买多少只公鸡,母鸡,小鸡?

                int x, y, z;

                for (x = 0; x <= 20; x++)

                    for (y = 0; y <= 33; y++)

                        for (z = 0; z <= 100; z++)

                            if ((x + y + z == 100) && (5 * x + y * 3 + z / 3 == 100) && (z % 3 == 0))

                                Console.WriteLine("公鸡|:{0}只,母?鸡:{1}只,小鸡:{2}只", x, y, z);

    上述运算执行的次数为21*34*101=71114

    问题的优化思想如下:

    问题中,由于三种鸡的和是固定的,因此只要枚举的两种鸡(x,y),第三种鸡就可以根据约定的条件求得(z=100-x-y),就这样就缩小了枚举的范围变成了双重循环。之所以选择Z,是因为Z的数值较大,优化的效果更好,此时的循环的次数就变成了:21*34=714。

    int x, y, z;

                for (x = 0; x <= 20; x++)

                    for (y = 0; y <= 33; y++)

                   {

                          z=100-x-y;

                  if ((x + y + z == 100) && (5 * x + y * 3 + z / 3 == 100) && (z % 3 == 0))

                                Console.WriteLine("公鸡|:{0}只,母?鸡:{1}只,小鸡:{2}只", x, y, z);

    }

    问题的再进一步的优化:

      如果从数学的角度来考虑枚举算法的进一步的优化,程序的效率就会进一步的优化

    根据题意:约束条件为:5X+3Y+Z/3=100;X+Y+Z=100;约去一个Z则得到7X+9Y=100;X+Y+Z=100;所以只要枚举出X(最多位14)则Y,Z的值就可以自然而然的得到确定了。

    计算1至N中数字X出现的次数,其中N〉=9,X为0-9

     

    方法1:采用枚举的算法,分立出1-N范围内所有的数据的每一位上的数字,查看是否为X,然后计数。

    int cnt = 0, i, k, n, x;

                n = Convert.ToInt32(Console.ReadLine());

                x = Convert.ToInt32(Console.ReadLine());

                for (i=1;i<=n;i++)

                {

                    k=i;

                    for (; k>0;k/=10)

                        if (k %10==x)

                            cnt++;

                }

                Console .WriteLine ("{0}",cnt);

    这个方法的缺点就是时间复杂度太高,计算市一个数中X的出现的次数的时间复杂度为O(log10N),计算全部的数中X的时间复杂度为O(nlog10N)

    算法的优化思维如下:

    利用数学公式直接计算最终的结果,一次求出数字中X在个无人,视为百威的出现的是次数,在相加得到最终的结果。这里X的范围为1-9,因为=0不符合下列规律,需要单独的计算。

    首先规律如下:

    (1)   从1到10,在他们的个位数中任意的X都出现了1次

    (2)   从1至100,在他们的十位数中,任意的X都出现了10次

    (3)   从1至1000,在他们的百位数中,任意的X都出现了100次

    以此类推,从1至10i,在他们的左数第二位(右数第i位)中,任意的X都出现了10i-1次。

    计算右数第i位包含的X的个数算法:

    (1)   取第i位左边(高位)的数字,乘以10i-1,得到基础值a。

    (2)   取第i位数字,计算修正值:

    如果大于X,则结果为a+10i-1

    如果小于X,则结果为a。

    如果等于X,则第i为右边(低位)数字,设为b,最后的结果为a+b+1。时间复杂度为

    O(log10N)

    代码如下:

       int cnt = 0, i, k, n, x, c;

                n = Convert.ToInt32(Console.ReadLine());

                x = Convert.ToInt32(Console.ReadLine());

                for (i = 1; (k = n / i) != 0; i*=10)

                {

                    cnt += (k / 10) * i;

                    c = k % 10;

                    if (c> k)

                        cnt += i;

                    else if (c == x)

                        cnt += n - k * i + 1;

                }

                Console.WriteLine("{0}", cnt);

     

    每天进步一点点;不为琐事困扰,每日岁月静好。
  • 相关阅读:
    通过异常处理错误-2
    通过异常处理错误-1
    线程池
    Synchronized
    持有对象-4
    持有对象-3
    持有对象-2 迭代器深入理解
    ServletContextListener
    持有对象-1
    行为参数化
  • 原文地址:https://www.cnblogs.com/Adaisme/p/7586089.html
Copyright © 2011-2022 走看看