Exercise 1;
#include <iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
double darts(int n);
int main()
{
clock_t start, finish;
int n[3] = {10000000, 100000000, 1000000000};
for(int i=0; i<3; i++)
{
start = clock();
cout << "n = " << n[i] << " Pi = " << darts(n[i]);
finish = clock();
cout << " Running time: " << finish-start << "ms" << endl;
}
return 0;
}
double darts(int n)
{
int k=0;
for(int i=0; i<n; i++)
{
double x=rand()/double(RAND_MAX);
//double y=rand()/double(RAND_MAX);
double y=x;
if(x*x+y*y<=1)
k++;
}
return 4.0*k/n;
}
Exercise 2:
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <time.h>
using namespace std;
double func(double x);
double HitorMiss(double (*func_ptr)(double), int n);
int main()
{
clock_t start, finish;
srand(unsigned(time(NULL)));
double (*fun)(double);
fun = func;
int n[3] = {10000000, 100000000, 1000000000};
for(int i=0; i<3; i++)
{
start = clock();
cout << "n = " << n[i] << " Pi = " << HitorMiss(fun, n[i]);
finish = clock();
cout << " Running time: " << finish-start <<endl;
}
return 0;
}
double func(double x)
{
double r;
if(x>1 || x<0)
cout << "x is out of range!!!" <<endl;
r = 1 - x * x;
return sqrt(r);
}
double HitorMiss(double (*func_ptr)(double), int n)
{
int k = 0;
for(int i=0; i<n; i++)
{
double x = rand()/double(RAND_MAX);
double y = rand()/double(RAND_MAX);
if(y < func_ptr(x))
k++;
}
return 4.0*k/n;
}
Exercise 3:
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <time.h>
using namespace std;
double func(double x);
double Integral(double (*func_ptr)(double), double a, double b, double c, double d, int n);
int main()
{
clock_t start, finish;
srand(unsigned(time(NULL)));
double (*fun)(double);
fun = func;
int n[3] = {1000000, 10000000, 100000000};
double a = 0;
double b = 1;
double c = 1;
double d = 5;
for(int i=0; i<3; i++)
{
start = clock();
cout << "n = " << n[i] << " Pi = " << Integral(fun, a, b, c, d, n[i]);
finish = clock();
cout << " Running time: " << finish-start <<endl;
}
return 0;
}
double func(double x)
{
double r;
r = 3*x*x + 2*x + 1;
return r;
}
double Integral(double (*func_ptr)(double), double a, double b, double c, double d, int n)
{
int k = 0;
double r;
for(int i=0; i<n; i++)
{
double x = rand()/double(RAND_MAX);
double y = 1 + 4.0 * rand()/double(RAND_MAX);
if(y < func_ptr(x))
k++;
}
r = 1.0 * k/n * (d - c) * (b - a) + c * (b - a);
return r;
}
Exercise9:
#include<iostream>
#include<math.h>
#include<time.h>//随机函数的种子
using namespace std;
#define AVG 200//产生200个正确的解,然后再统计相关数据
int failure = 0; //算法运行失败的次数
int success = 0; //算法运行成功的次数
int nsnode = 0; //一次成功搜索访问的结点数
int nfnode = 0; //一次不成功搜索访问的结点数
int tempLVNode = 0;
int tempBackNode = 0;
class RandomNumber
{
public: int Random(int n)
{
//生成0 ~ n-1之间的随机整数,n不大于32767
if (n>32767)
{
cout << "您输入的n值不能大于32767" << endl;
exit(-1);
}
int x;
x = rand();
return x%n;
}
};
class Queen
{
friend void nQueen(int n, int stopVegas);
public:
Queen(int n);
bool Place(int k); //测试皇后k置于第x[k]列的合法性, 注意:x[k]的值可以取从1到n
bool Backtrack(int t); //解n后问题的回溯法
bool QueensLV(int stopVegas); //随机放置stopVegas个皇后的LV算法
int n, *x, *y; //x,y 是解向量
};
Queen::Queen(int m)
{
n = m;
}
bool Queen::Place(int k)
{
for (int j = 1; j<k; j++)
{
if ((abs(k - j) == abs(x[k] - x[j])) || (x[j] == x[k]))
return false;
}
return true;
}
bool Queen::Backtrack(int t)
{
if (t>n)
{
for (int i = 1; i <= n; i++)
y[i] = x[i];
return true;
}
else
{
for (int i = 1; i <= n; i++)
{
x[t] = i;
if (Place(t) && Backtrack(t + 1)) //要理解回溯法的精髓
{
tempBackNode++;
return true;
}
}
}
tempBackNode++;//某皇后放置失败
return false;
}
bool Queen::QueensLV(int stopVegas)
{
RandomNumber rnd; //随机数生成器
int k = 1; //从第1个皇后开始放置
int count = 1;
tempLVNode = 0;
while ((k <= stopVegas) && (count>0))
{
count = 0;
for (int i = 1; i <= n; i++)
{
x[k] = i;
//tempLVNode++;
if (Place(k))
y[count++] = i; //数组y中存放的是放置皇后k,可用的列号,以便于等会随机选择第k个皇后的位置
}
if (count>0)
{
//皇后k可以找到一个随机放置的位置
int r = rnd.Random(count);
x[k++] = y[r]; //随机选择一列放置皇后k,然后k++,继续while循环
tempLVNode++;
}
else
{
//皇后k找不到随机放置的位置,QueensLv算法失败
}
}
return (count>0); //表示放置成功
}
void nQueen(int n, int stopVegas)
{
Queen X(n);
//初始化X
int *p = new int[n + 1];
int *q = new int[n + 1];
for (int i = 0; i <= n; i++)
{
p[i] = 0;
q[i] = 0;
}
X.x = q;
X.y = p;
failure = 0; //算法运行失败的次数
success = 0; //算法运行成功的次数
nsnode = 0; //一次成功搜索访问的结点数
nfnode = 0; //一次不成功搜索访问的结点数
while (1)
{
while (1)
{
if (!X.QueensLV(stopVegas)) //说明随机放置部分算法失败
{
nfnode += tempLVNode;
//nsnode+=tempLVNode;
failure++;
//cout<<"LV搜索失败,算法重新搜索...."<<endl;
}
else
{
//随机放置部分算法成功,但还不能保证整个算法运行成功,还要看回溯部分是否成功,才能确定算法成功
//cout<<"LV随机放置完毕"<<endl;
break; //推出while循环,开始回溯
}
}//while.....LV的循环搜索,直到成功为止
//算法回溯部分
//cout<<"开始回溯..."<<endl;
tempBackNode = 0;
if (X.Backtrack(stopVegas + 1))
{
//回溯搜索成功
//cout<<"回溯成功,"<<n<<"皇后问题找到正确解。"<<endl;
nsnode += tempLVNode;//LV算法部分搜索的结点数也要算在其内
nsnode += tempBackNode;
success++;
if (success >= AVG)
break;
}
else
{
//回溯部分搜索失败,这也是由随机放置皇后的算法运行的结果导致的失败
failure++;
nfnode += tempLVNode;
nfnode += tempBackNode;
//cout<<"回溯失败!!"<<endl;
}
}//while.....LV成功后,若回溯失败,则继续循环搜索,直到成功AVG次为止,然后求平均值
}
int main()
{
int n, stopVegas, Beststop;
float p, s, e, t;
float tArray[21];
srand(time(0));//为随机数的生成选定种子
/***********实现结果向文件中输出**********************/
FILE *fp; //声明文件指针
fp = fopen("result.txt", "a+");//新建文件,文件名自定,保存路径自定注意/必须为//转义字符
if (!fp)
{
printf("File Open ERROR!");
exit(-1);
}
for (n = 8; n <= 20; n++)
{
fprintf(fp, "\nstopVegas\tp\t\ts\t\te/t\tt\n");
for (stopVegas = 0; stopVegas <= n; stopVegas++)
{
nQueen(n, stopVegas);
p = (float)success / (success + failure);
s = (float)nsnode / success; //一次 成功搜索访问的结点数平均值s
if (failure == 0) //一次不成功搜索访问的结点数平均值e
{
e = 0;
}
else
{
e = (float)nfnode / failure;
}
tArray[stopVegas] = s + ((1 - p)*e) / p; //反复调用算法使得最终找到一个解所访问的结点数的平均 值t
fprintf(fp, "\n%d\t\t%f\t%f\t%f\t%f\n", stopVegas, p, s, e, tArray[stopVegas]);
}
//找出t值最小的stopVegas值
t = tArray[0];
for (int m = 1; m <= n; m++)
{
if (tArray[m]<t)
{
t = tArray[m];
Beststop = m;
}
}
cout << "n=" << n << "," << "stopVegas=" << Beststop << "时,算法效率很高。" << endl;
fprintf(fp, "/n当n=%d时,取stopVegas=%d时,算法效率很高/n", n, Beststop); //文件输出结果
}
fclose(fp);
return 1;
}
Exercise10:
#include<iostream>
#include<cmath>
#include<random>
#include<ctime>
using namespace std;
bool isprime(int n);
bool Btest(int a, int n);
bool MillRab(int n);
bool RepeatMillRab(int n, int k);
int PrintPrimes();
int ModularExponent(int a, int j, int p);//get s=a^j (mod p)
int main()
{
int Naive_Count=1, MC_Count;
for (int n = 3; n < 10000; n = n + 2)
{
if (isprime(n))
{
cout << n << " ";
Naive_Count++;
}
}
MC_Count = PrintPrimes();
cout << "100 ~ 10000之之间素数个数:" << endl;
cout << "朴素算法:" << Naive_Count-25 << endl;//100以内素数个数为25
cout << "MC概率算法:" << MC_Count-25 << endl;
cout << endl;
return 0;
}
bool isprime(int n)
{
for (int i = 2; i*i < n+1; i++)
if (n%i == 0)
return false;
return true;
}
int PrintPrimes()
{
int count = 2;
//cout << 2 << " " << 3 << " ";
int n = 5;
do {
int k = floor(log2(n));
if (RepeatMillRab(n, k))
{
//cout << n << " ";
count++;
}
n = n + 2;
} while (n<10000);
return count;
}
bool RepeatMillRab(int n, int k)
{
for (int i = 1; i < k + 1; i++)
{
if (MillRab(n) == false)
return false;
}
return true;
}
bool MillRab(int n)
{
srand(unsigned(time(0)));
int a = 2 + rand() % (n - 3);
return Btest(a, n);
}
bool Btest(int a, int n)
{
int s = 0;
int t = n - 1;
do {
s++; t = t / 2;
} while (t % 2 == 0);
int x = ModularExponent(a, t, n);
if (x == 1 || x == n - 1)
return true;
for (int i = 1; i < s; i++)
{
x = (x*x) % n;
if (x == n - 1)
return true;
}
return false;
}
int ModularExponent(int a, int j, int p)
{
int s = 1;
while (j>0)
{
if (j % 2 == 1)
s = (s*a) % p;
a = (a*a) % p;
j = j / 2;
}
return s;
}