一种应用于填空题的随机算法

最后主导做一个考试系统,然而在为试卷出一份填空题的时候却遇到了麻烦,时间复杂度较大,耗时太长。虽然使用PHP开发,但是跟根我的经验,在数量级10^2级,出几个填空题竟然要花上5分钟来查找合适的题目,简直太扯淡了。

根据当前的实际情况:

1.题库中题目的空格数不连续且不确定

2.限制空数

3.题数可以不限定

4.要求在数秒之内生成题目

在询问PHP开发人员之后,发现找出方案的时间,确实常常在5分钟。使用C++实现并打印方案时,发现时间耗费也相当可怕。

稍后关闭所有打印,再次执行,发现30秒以内即可找出所有可能方案。方法如下:

void Situation(int nBlank/*空数*/,int min/*下限*/,int max/*上限*/, vector<int> &vec/*方案*/)
    {
        for (int i=min; i<=max; ++i)
        {
            vec.push_back(i);//压入当前值
            int t = Sum(vec);
            if (t<nBlank)
            {
                Situation(nBlank,min,max,vec);//方案待完成
            }
            else if (t == nBlank)
            {
                m_vv.push_back(vec);//得到方案
                //PrintV(vec);
                //break;
            }
            else if (t > nBlank)
            {
                ;//break;//方案失败,一般不会到这儿
            }
            vec.pop_back();//弹出当前值
        }
    }

但是时间仍然长达30秒,且方案数达到数十万中,仍然需要优化,回想最开始根据每题的平均空数去取最大概率方案的方法,弊端也是显而易见的:

1.取不到其它方案

1.离平均空数较远的题恐怕永远选不到

因此想到了随机的方案:

1.每次从空格数队列中随机取出一个值,并将此值从本次取值的空格数队列中移除,表示取过了。空格数达不到要求则从最原始的空格队列 中取下一次值

2.直到取到最后一个值,此时空格数要么等于要求值,要么大于要求值

3.等于时,即成功取到方案,退出,大于时失败,需要回归到上一次,从余下的值中随机一个继续查找,直到取到等于的情况,则退出

方法如下:

int RandomV(vector<int> &v)
    {
        srand(time(NULL));//设定一个随机种子
        int i = rand();    //在0-0x7fff取一个随机值
        i = i%(v.size()-1);//换算队列的一个随机序号
        int n = v[i];//取出该序号对应的值
        v.erase(v.begin()+i);//从队列擦除该值

        return n;
    }


bool SituationVR(int nBlank,vector<int>const v,vector<int> &vec)
    {
        vector<int> v_ = v;            //拷贝一个备份出来
        for ( ; v_.size()>0; )
        {
            int i = RandomV(v_);    //从空格数队列中以时间作为种子,随机取出一个值,并删除已取过的值

            vec.push_back(i);        //压入当前值

            int t = Sum(vec);        //求当前累积空数

            if (t<nBlank)            //方案待完成
            {
                if (SituationVR(nBlank,v,vec))
                {
                    return true;
                }
            }
            else if (t == nBlank)
            {
                PrintV(vec);
                m_vv.push_back(vec);    //得到方案
                return true;
            }
            else if (t > nBlank)
            {
                vec.pop_back();        //弹出当前值
                break;                //方案失败,一般不会到这儿
            }
            vec.pop_back();            //弹出当前值
        }
        return false;                //默认返回假
    }

每次执行时间几乎察觉不到,快速生成一个方案且结果随机。确实是一个生成填空题的绝佳算法。

猜你喜欢

转载自www.cnblogs.com/ice-arrow/p/11436334.html