Touge コンピュータアルゴリズムの設計と解析: ランダム化アルゴリズム

レベル 1: コイン実験

任务描述
相关知识
    随机数
编程要求
测试说明

タスクの説明
このレベルのタスク: コイン投げ実験をシミュレートするためにコンピューターによって生成された擬似乱数。

関連知識
このレベルのタスクを完了するには、1. 配列の長さを取得する方法、2. 配列を走査する方法を習得する必要があります。

乱数 乱数
は、ランダム化アルゴリズムの設計において非常に重要な役割を果たします。
実際のコンピュータ上では実際の乱数を生成することはできないため、ランダム化アルゴリズムで使用される乱数はすべてある程度ランダム、つまり疑似乱数です。

コイン投げの実験は、コンピューターで生成された擬似乱数を使用してシミュレートされます。
コインを 10 回投げ、各コインのトスで表と裏がランダムに得られると仮定します。10 回のコイン投げでイベントが構成されます。
Random(2) を呼び出すと、バイナリの結果が返されます。
メイン プログラムでは、関数 TossCoins が繰り返し呼び出され、10 枚のコインを 50,000 回投げるイベントをシミュレートします。
これらの 50,000 回のシミュレーションを頭記録すると、正確に頭刺しが得られます。最終出力は、コイン投げイベントをシミュレートすることによって取得された表イベントの確率マップです。

プログラミング要件
プロンプトに従って、右側のエディターでコードを補足します。

テストでは、
RandomNumber.h 関数が記述されていることを示しており、クリックして表示できます。

プラットフォームは、作成したコードをテストします。
例:
input:
10
50000
Output:

    0 *
    1 *
    2   *
    3        *
    4              *
    5                 *
    6              *
    7        *
    8   *
    9 *
    10 *`
#include "RandomNumber.h"
#include <iostream>
using namespace std;
int TossCoins(int numberCoins);
int main()
{
    
    
    //模拟随机抛硬币事件
    int NCOINS;
    long NTOSSES;
    cin >>NCOINS;
    cin >>NTOSSES;
    //heads[i]是得到i次正面的次数
    long i,heads[NCOINS+1];
    int j,position;
    //初始化数组heads
    for(int j=0; j<NCOINS+1;j++)
    {
    
    
        heads[j] = 0;
    }
    //重复50,000次模拟事件
    for(int i=0; i<NTOSSES; i++)
    {
    
    
        heads[TossCoins(NCOINS)]++;
    }
    //输出频率图
    for(int i=0; i<=NCOINS; i++)
    {
    
    
        position = int(float(heads[i])/NTOSSES*72);
        cout<<i<<" ";
        for(int j=0; j<position-1; j++)
        {
    
    
            cout<<" ";
        }
        cout<<"*"<<endl;
    }
    return 0;
}
int TossCoins(int numberCoins)
{
    
    
    //随机抛硬币
    static RandomNumber coinToss(1);
    int i,tosses = 0;
    for(int i=0; i<numberCoins; i++)
    {
    
    
        //Random(2) = 1表示正面
        tosses += coinToss.Random(2);
    }
    return tosses;
}

レベル 2: ランダムに点を投げる方法で円周率を求める

    任务描述
    相关知识
    编程要求
    测试说明

タスクの説明
このレベルのタスク: ランダム キャスト法によって円周率を計算するプログラムを作成する

関連する知識
ここに画像の説明を挿入
プログラミング要件
プロンプトに従って、右側のエディターでコードを補足します。
テスト手順
プラットフォームは、作成したコードをテストします。
入力:

100

出力:

n1=100
pi=3.12

ミッションを始めましょう。成功を祈っています!

//随机化算法 用随机投点法计算π值
#include "RandomNumber.h"
#include <iostream>
using namespace std;
double Darts(int n);
int main()
{
    
    
    int n1;
    cin>> n1;
    cout<<"n1="<<n1<<"\npi="<<Darts(n1)<<endl;
    return 0;
}
//用随机投点法计算π值
double Darts(int n)
{
    
    
    static RandomNumber dart(1);
    int k = 0;
    for(int i=1; i<=n; i++)
    {
    
    
        double x = dart.fRandom();
        double y = dart.fRandom();
        if((x*x + y*y)<=1)
        {
    
    
            k++;
        }
    }
    return 4*k/double(n);
}

レベル 3: 非線形方程式を解く

任务描述
相关知识
编程要求
测试说明

タスクの説明
このレベルのタスク: 線形方程式を見つけるプログラムを作成します。

関連知識
次の非線形方程式を解くための
ここに画像の説明を挿入
ここに画像の説明を挿入
プログラミング要件
単純な 2 次元線形方程式を求めます。
x1-x2=fx1
x1+x2=fx2
プロンプトに従って、右側のエディターでコードを補足します。
テスト手順
プラットフォームは、作成したコードをテストします。
例:
入力:
1
3
出力:
元の方程式は次のとおりです:
x1-x2=1
x1+x2=3
根は次のとおりです:
x1=2.02104 x2=1.01445

ミッションを始めましょう。成功を祈っています!

//随机化算法 解线性方程组
#include "RandomNumber.h"
#include <iostream>
using namespace std;
bool NonLinear(double *x0,double *dx0,double *x,double *fx,double a0,
                    double epsilon,double k,int n,int Steps,int M);
double f(double *x,double *fx);
int main()
{
    
    
    double  *x0,                //根初值
            *x,                    //根
            *dx0,            //增量初值
            *fx,  // 函数值
            a0 = 0.0001,            //步长
            epsilon = 0.01,        //精度
            k = 1.1;            //步长变参
    int n = 2,                    //方程个数
        Steps = 10000,            //执行次数
        M = 1000;                //失败次数
    x0 = new double[n+1];
    dx0 = new double[n+1];
    x = new double[n+1];
    fx = new double[n+1];
    cin >> fx[1];
    cin >> fx[2];
    //根初值
    x0[1] = 0.0;
    x0[2] = 0.0;
    //增量初值
    dx0[1] = 0.01;
    dx0[2] = 0.01;
    cout<<"The original equations are:"<<endl;
    cout<<"x1-x2="<<fx[1]<<endl;
    cout<<"x1+x2="<<fx[2]<<endl;
    cout<<"The roots are:"<<endl;
    bool flag = NonLinear(x0,dx0,x,fx,a0,epsilon,k,n,Steps,M);
    while(!flag)
    {
    
            
        flag = NonLinear(x0,dx0,x,fx,a0,epsilon,k,n,Steps,M);
    }    
    for(int i=1; i<=n; i++)
    {
    
    
        cout<<"x"<<i<<"="<<x[i]<<" ";
    }
    cout<<endl;
    return 0;
}
//解非线性方程组的随机化算法
bool NonLinear(double *x0,double *dx0,double *x,double *fx,double a0,
                    double epsilon,double k,int n,int Steps,int M)
{
    
    
    static RandomNumber rnd(1);
    bool success;            //搜索成功标志
    double *dx,*r;
    dx = new double[n+1];    //步进增量向量
    r = new double[n+1];    //搜索方向向量
    int mm = 0;                //当前搜索失败次数
    int j = 0;                //迭代次数
    double a = a0;            //步长因子
    for(int i=1; i<=n; i++)
    {
    
    
        x[i] = x0[i];
        dx[i] = dx0[i];
    }
    double fy = f(x,fx);        //计算目标函数值
    double min = fy;        //当前最优值
    while(j<Steps)
    {
    
    
        //(1)计算随机搜索步长
        if(fy<min)//搜索成功
        {
    
    
            min = fy;
            a *= k;
            success = true;
        }
        else//搜索失败
        {
    
    
            mm++;
            if(mm>M)
            {
    
    
                a /= k;
            }
            success = false;
        }
        if(min<epsilon)
        {
    
    
            break;
        }
        //(2)计算随机搜索方向和增量
        for(int i=1; i<=n; i++)
        {
    
    
            r[i] = 2.0 * rnd.fRandom()-1;
        }
        if(success)
        {
    
    
            for(int i=1; i<=n; i++)
            {
    
    
                dx[i] = a * r[i];
            }
        }
        else
        {
    
    
            for(int i=1; i<=n; i++)
            {
    
    
                dx[i] = a * r[i] - dx[i];
            }
        }
        //(3)计算随机搜索点
        for(int i=1; i<=n; i++)
        {
    
    
            x[i] += dx[i];
        }
        //(4)计算目标函数值
        fy = f(x,fx);
        j++;
    }    
    if(fy<=epsilon)
    {
    
    
        return true;
    }
    else
    {
    
    
        return false;
    }
}
double f(double *x, double* fx)
{
    
    
    return (x[1]-x[2]-fx[1])*(x[1]-x[2]-fx[1])
            +(x[1]+x[2]-fx[2])*(x[1]+x[2]-fx[2]);
}

Acho que você gosta

Origin blog.csdn.net/m0_63007797/article/details/130606376
Recomendado
Clasificación