一道经典算法题的分析及代码实现

近期从网上看到一个算法题,感觉蛮有意思的,就研究了吧,题目如下:

某种传染病第一天只有一个患者,前五天为潜伏期,不发作也不会传染人,第6天开始发作,从发作到治愈需要5天时间,期间每天传染3个人,求第N天共有多少患者。

现将自己的分析求解过程分享如下,跟大家一起探讨学习,有不对的地方,忘请指教。

直接上代码,分析过程在头注释里:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    /*
     * 某种传染病第一天只有一个患者,前五天为潜伏期,不发作也不会传染人
     * 第6天开始发作,从发作到治愈需要5天时间,期间每天传染3个人求第N天
     * 共有多少患者
     */

    /*
     * 解答思路:递归推理建立数学模型
     * 根据题目将患者分为潜伏期病人和发作期病人,那假设第n天的潜伏期患者为f(n),
     * 再假设第n天的发作期患者为y(n),则最后的总患者数应该=f(n) + y(n).
     * 下面我们来分析下前一天的潜伏期患者f(n-1)同f(n)的关系,以及前一天的发作期
     * 患者y(n-1)同y(n)的关系,然后来建立数学模型。因为病情的变化是以5天为一个变化周期,其中就存在
     * 以下几个变化量:
     * △f:从n-1天到n天潜伏期患者的新感染数量
     * △c:从n-1天到n天由潜伏期转发作期的患者数量
     * △y:从n-1天到n天康复的患者数量
     * 有了以上几个变化量,我们可以简单列出前后两天的两种患者的数量的变化关系:
     * f(n-1)-△c+△f=f(n)----------(1)
     * y(n-1)+△c-△y=y(n)----------(2)
     * 下面的关键就是求解以上的三个增量,我们要利用两个重要的已知条件,一个是发作期的患者每天传染3
     * 个新患者,二是5天一个病情(包括新感染进入潜伏期、由潜伏期变为发作期以及康复)变化期,所以我们
     * 能得到:
     * △f=3*y(n)
     * △c稍微有点难度,仔细分析下是可以得到的,第n天的进入发作期的患者,正是5天前刚进入潜伏期的
     * 患者数3*y(n-5),所以
     * △c=3*y(n-5)
     * 所以至此公式(1)已经出来了,为:
     * f(n-1)-3*y(n-5)+3*y(n)=f(n)---------(3)
     * 下面还有(2)中还有个△y未解,这个有点难度,我们来推理下,要求第n天的康复患者数,可以推理为求
     * 第n-5天的新进入发作期的患者数,我们设这个数为x,然后利用公式(1)可以来推导出第n-5天的时候的潜伏期
     * 的变化关系为
     * f(n-6)-x+3*y(n-5)=f(n-5) => x=f(n-5)-f(n-6)-3*y(n-5),故△y=x即为
     * △y=f(n-5)-f(n-6)-3*y(n-5)
     * 以上变化量的求解是建立数学模型的关键。这样将△y代入公式(2),并化简得到:
     * y(n-1)+f(n-5)-f(n-6)=y(n)-----------(4)
     * 自此公式(3)和(4)即为最终的数学模型,编码中的递归推导按照此公式来即可求解,
     * f(n)对应PreSick(int n)递归方法,y(n)对应Sick(int n)递归方法。需要注意的是
     * 对于n<7以下的递归结束条件下,要给出直接的数字。
     */

    class Program
    {
        static void Main(string[] args)
        {
            string inputDays = Console.ReadLine();
            int n = Convert.ToInt32(inputDays);
            int HowMany = PreSick(n) + Sick(n);
            Console.WriteLine(HowMany);
        }

        static int PreSick(int n)
        {
            if (n == 7)
            {
                return 6;
            }
            else if (n == 6)
            {
                return 3;
            }
            else if (n < 6)
            {
                return 1;
            }
            else
            {
                //f(n)=f(n-1)-3*y(n-5)+3*y(n)---------(3)
                return PreSick(n - 1) - 3 * Sick(n - 5) + 3 * Sick(n);
            }
        }

        static int Sick(int n)
        {
            if (n < 7 && n > 5)
            {
                return 1;
            }
            else if (n <= 5)
            {
                return 0;
            }
            else
            {
                //y(n)=y(n-1)+f(n-5)-f(n-6)-----------(4)
                return Sick(n-1) -PreSick(n-6) + PreSick(n-5);
            }
        }
    }
}

posted on 2011-06-17 15:20  Jordan_Fei  阅读(1512)  评论(4编辑  收藏  举报

导航