数学建模实验报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

数学建模实验报告
1.流⽔问题
问题描述:
⼀如下图所⽰的容器装满⽔,上底⾯半径为r=1m,⾼度为H=5m,
在下地⾯有⼀⾯积为
B0.001m2的⼩圆孔,现在让⽔从⼩孔流出,问⽔什么时候能流
完?
解题分析:
这个问题我们可以采⽤计算机模拟,⼩孔处的⽔流速度为V=sqrt[2*g*h],单位时间从⼩孔流出的⽔的体积为V*B,再根据⼏何关系,求出⽔⾯的⾼度H,时间按每秒步进,记录点(H,t)并画出过⽔⾯⾼度随时间的变化图,当⽔⾯⾼度⼩于0.001m 时,可以近似认为⽔流完了。

程序代码:
Methamatic程序代码:
运⾏结果:
(5)结果分析:
计算机仿真可以很直观的表现出所求量之间的关系,从图中我们可以很⽅便的求出要求的值。

但在实际编写程序中,由于是初次接触methamatic 语⾔,对其并不是很熟悉,加上个⼈能⼒有限,所以结果可能不太精确,还请见谅。

2.库存问题
问题描述某企业对于某种材料的⽉需求量为随机变量,具有如下表概率分布:
每次订货费为500元,每⽉每吨保管费为50元,每⽉每吨货物缺货费为1500元,每吨材料的购价为1000元。

该企业欲采⽤周期性盘点的),(S s 策略来控制库存量,求最佳的s ,S 值。

(注:),(S s 策略指的是若发现存货量少于s 时⽴即订货,将存货补充到S ,使得经济效益最佳。


问题分析:
⽤10000个⽉进⾏模拟,随机产⽣每个⽉需求量的概率,利⽤计算机编程,将各种S 和s 的取值都遍历⼀遍,把每种S,s的组合对应的每⽉花费保存在数组cost数组⾥,并计算出平均⽉花费average,并⽤类answer来记录,最终求出对应的S和s。

程序代码:
C++程序代码:
#include
#include
#include
#include
#define Monthnumber 10000
int Need(float x)
{
int ned = 0;//求每个⽉的需求量
if(x < 0.05)
ned = 50;
else if(x < 0.15)
ned = 60;
else if(x < 0.30)
ned = 70;
else if(x < 0.55)
ned = 80;
else if(x < 0.75)
ned = 90;
else if(x < 0.85)
ned = 100;
else if(x < 0.95)
ned = 110;
else ned = 120;
return ned;
}
class A
{
public:
int pS;
int ps;
float aver;
};
int main()
{
A answer;
answer.aver=10000000;
//int cost[Monthnumber+1]={0}; float average=0;
int i;
float x;
int store[Monthnumber];
//srand((int)time(0));
for(int n=6;n<=12;n++)
{
// int n=11;
int S=10*n;
for(int k=5;k
{
// int k=5;
int s=k*10;
average=0;
int cost[Monthnumber+1]={0};
for(i=1;i<=Monthnumber;i++)
{
store[i-1]=S;
srand(time(0));
x=(float)rand()/RAND_MAX; //产⽣随机数
//cout<<" "<
//cout<
int need=Need(x);
if(need>=store[i-1])
{
cost[i]= 1000*S + (need - store[i-1])*1500 + 500;
store[i]=S;
}
else if(need>=store[i-1]-s)
{
cost[i]=1000*(need+S-store[i-1]) + 50*(store[i-1]-need) + 500; store[i]=S;
}
else
{
cost[i]=(store[i-1]-need)*50;
store[i]=store[i-1]-need;
}
average=cost[i]+average;
}
average=average/Monthnumber;
cout<<"n="<
cout<<"花费最少时s应该为:"<
cout<<"平均每⽉最少花费为:"<
}
运⾏结果:
结果分析:
⽤计算机模拟的结果和⽤数学分析的结果有⼀定的差异,由于计算机模拟时采⽤的是随机模型⽽我⽤time函数和rand函数产⽣真随机数,所以在每次的结果上会有所差异,但对于⼀般的⽣产要求亦可以满。

3.锁具问题
问题描述
某⼚⽣产⼀种弹⼦锁具,每个锁具有n个槽,每个槽的⾼度从{1,2,3,4}这四个数中任取⼀个,限制最少有⼀个相邻的槽⾼之差为3,且⾄少有三个不同的槽⾼。

每个槽的⾼度取遍这四个数且满⾜上边这两个限制条件是⽣产出⼀批锁,求⼀批锁的把数。

问题分析
可以采⽤递归的算法,使得每个槽都从1取到4,然后设置两个判断条件,即不同槽数⼤于等于3,相邻槽⾼之差最⼤值要⼤于等于3,满⾜这两个条件后,计数变量total就加⼀来记录数据。

程序代码
C++代码:
#include
#include
int amax=0;
int amin=100000;
int lim=0;
int neighbor=0;
int total=0;
#define N 10
int a[N+1]={0};
int max(int *x)
{
int Max=-1;
for(int i=1;i<=N;i++)
{
if((x[i]>Max)&&(x[i]<5))
Max=x[i];
return Max;
}
int min(int *x)
{
int Min=10;
for(int i=1;i<=N;i++)
{
if((x[i]0))
Min=x[i];
}
return Min;
}
int abs(int x)
{
if(x>=0)
return x;
return -x;
}
int lockset(int n)
{
int i ;
if(n==0)return 0;
if(n==1)
{
for(a[n]=1;a[n]<=4;a[n]++)
{
//lockset(n-1);
amax=max(a);
amin=min(a);
lim=0;
for(i=1;i<=N;i++) //判断不同属的个数{
if(a[i]!=0)
lim=(amax-a[i])*(a[i]-amin)+lim;
neighbor=0; //判断相邻⾼度
for(i=1;i
{
if((a[i]!=0)&&(a[i+1]!=0)&&(abs(a[i]-a[i+1])>neighbor)) neighbor=abs(a[i]-a[i+1]);
}
if(((lim>0)&&(neighbor==3)))
total++;
//cout<
}
}
else
for(a[n]=1;a[n]<=4;a[n]++)
{
lockset(n-1);
}
return 0;
}
int main()
{ int n;
cout<<"请输⼊槽数"<
cin>>n;
lockset(n);
cout<<"\n"<
return 0;
}
运⾏结果:
结果分析:
本题通过递归地⽅法来穷举出所有情况,当该情况满⾜题⽬条件时total就记录⼀次,但该⽅法⽐较费时间,并且当槽数较⼤时可能会出错,可以在开始时加⼀个判断语句,科技较少时间。

4.层次分析法
问题描述
⼀位四年级⼤学⽣正在从若⼲个招聘单位中挑选合适的⼯作岗位,他考虑的主要因素包括发展前景、经济收⼊、单位信誉、地理位置等。

试建⽴模型给他提出决策建议。

问题分析
xi表⽰要考虑的因素,yi表⽰考虑对象,
x1:发展前景;x2:经济收⼊;x3:单位信誉;x4:地理位置
然后进⾏迭代:
③成对⽐较并赋值:
x1/x2=1, x1/x3=6/5, x1/x4=2, x2/x3=1.2
x2/x4=2, x3/x4=5/3
④建⽴逆对称矩阵
1 1 5/6 0.5
A= 1 1 5/6 0.5
1.2 1.2 1 3/5
2 2 5/
3 1
利⽤MATLAB实现迭代求解
程序代码:
A=[1,1,6/5,2;1,1,6/5,2;5/6,5/6,1,5/3;1/2,1/2,3/5,1] e0=[1/4;1/4;1/4;1/4];
e=[0;0;0;0];
e1=e0;
y1=[7,8,9,6];
y2=[9,7,7,7];
y3=[8,9,9,8];
y4=[8,8,8,7];
while e~=e1
e=e1;
step=A*e;
sum=0;
for i=1:1:4
sum=sum+step(i)
end
e1=(1/sum)*step
end
scorey1=0;
scorey2=0;
scorey3=0;
scorey4=0;
for i=1:1:4
scorey1=scorey1+e(i)*y1(i);
end
for i=1:1:4
scorey2=scorey2+e(i)*y2(i);
end
for i=1:1:4
scorey3=scorey3+e(i)*y3(i);
end
for i=1:1:4
scorey4=scorey4+e(i)*y4(i);
end
score=[scorey1;scorey2;scorey3;scorey4] for j=1:1:3 if score(j)>score(j+1)
choose=j;
else choose=j+1 ;
end
end
j
运⾏结果:
按所得结果可知:第三家公司的得分最⾼。

故选择第三家公司,即Apple
结果分析:
由于每个⼈对每个因素的看重程度不同,所以判断矩阵因⼈⽽异,这样层次分析法就很适应于具体的对象,将定性的问题量化,便于分析,得出结论。

5.⽔道测量数据
问题描述
表1给出了在以码为单位的直⾓坐标为X,Y的⽔⾯⼀点处以英尺计的⽔深Z。

⽔深数据是在低潮时测得的。

船的吃⽔深度为5英尺。

在矩形区域(75,200)×(-50,150)内的哪些地⽅船要避免进⼊。

1
X 129.0 140.5 103.5 88.0 185.5 195.0 105.5
157.5 107.5 77.0 81.0 162.0 162.0 117.5
Y 7.5 141.5 23.0 147.0 22.5 137.5 85.5
-6.5 -81.0 3.0 56.5 -66.5 84.0 -33.5
问题分析:本题都是离散
点,所以可以先
插值,再画图。

最后画出等⾼线。

来判断海底的地貌,从等⾼线上判断.
程序代码:
x=[129 140 103.5 88 185.5 195 105 157.5 107.5 77 81 162 162 117.5];
y=[7.5 141.5 23 147 22.5 137.5 85.5 -6.5 -81 3 56.5 -66.5 84 -33.5];
z=[4 8 6 8 6 8 8 9 9 8 8 9 4 9];
xi=75:3:200; yi=-50:3:150;
figure(1)
z1i=griddata(x,y,z,xi,yi','nearest'); %最邻近插值 surfc(xi,yi,z1i)
xlabel('X'),ylabel('Y'),zlabel('Z') title('最邻近插值')
figure(2)
z2i=griddata(x,y,z,xi,yi'); %双线性插值 surfc(xi,yi,z2i)
xlabel('X'),ylabel('Y'),zlabel('Z') title('双线性插值')
figure(3) %双三次插值 z3i=griddata(x,y,z,xi,yi','cubic'); surfc(xi,yi,z3i) xlabel('X'),ylabel('Y'),zlabel('Z') title('双三次插值')
figure(4)
subplot(1,3,1),contour(xi,yi,z1i,5,'r'); %创建⼦图,画等⾼线 title('最邻近插值') subplot(1,3,2),contour(xi,yi,z2i,5,'r'); title('双线性插值')
subplot(1,3,3),contour(xi,yi,z3i,5,'r'); title('双线性插值') 运⾏结果:
Z 4 8 6 8 6 8 8
9 9 8 8 9 4 9
结果分析
由于对MA TLAB了解有限,所以本体是仿照例题做的,但通过模仿,对MATLAB有了更深层次的了解,从中获益匪浅。

6.⿊⽩球问题
问题描述
如下图所⽰,27个⽴⽅形空盒排成3×3×3的三位列阵。

如果三个盒⼦在同⼀条⽔平线上,或同⼀条垂直线上,或同⼀条对⾓线上,则认为三盒⼀线。

这样的线共有49条:⽔平线18条,垂直线9条,⽔平⾯对⾓线6条,垂直⾯对⾓线12条,对⾓⾯对⾓线4条。

现有⽩球13个,⿊球14个,每个盒⼦中放⼊⼀个球,求单⼀⾊球的最少线数。

问题分析
这个问题和锁具的那个问题很相像,也⽤递归模拟,⽤1代表⽩球,0代表⿊球,并且⽤blacknumber和whitenumber来记录⿊⽩球的数量,从⽽模仿问题,⽤穷举的⽅法来试探,并且记录每次对⾓线的个数,并记录最⼩的,最后输出。

程序代码:
C++代码:
#include
#include
int Box[3][3][3];
//int total=0;
int n;
int min=1000;
enum ballcolor{black=0,white=1};
int Min(int x,int y)
{
if(x
return x;
return y;
}
int test()
{ int total=0;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
//for(int k=1;k<3;k++)
//-----------------------------------------------------------------------------------------------------------//18条⽔平线和9条垂直线
if((Box[i][j][0]==Box[i][j][1])&&(Box[i][j][1]==Box[i][j][2])) total++;
if((Box[i][0][j]==Box[i][1][j])&&(Box[i][1][j]==Box[i][2][j])) total++;
if((Box[0][i][j]==Box[1][i][j])&&(Box[1][i][j]==Box[2][i][j])) total++;
}
//------------------------------------------------------------------------------------------------------------//6条⽔平⾯对⾓线和12条垂直⾯对⾓线if((Box[i][0][0]==Box[i][1][1])&&(Box[i][1][1]==Box[i][2][2]))
total++;
if((Box[0][i][0]==Box[1][i][1])&&(Box[1][i][1]==Box[2][i][2]))
total++;
if((Box[0][0][i]==Box[1][1][i])&&(Box[1][1][i]==Box[2][2][i]))
total++;
if((Box[0][2][i]==Box[1][1][i])&&(Box[1][0][i]==Box[1][0][i]))
total++;
if((Box[i][2][0]==Box[i][1][1])&&(Box[i][1][1]==Box[i][0][1]))
total++;
if((Box[0][i][2]==Box[1][i][1])&&(Box[1][i][1]==Box[1][i][0]))
total++;
}
//-----------------------------------------------------------------------------------------------------------//4条对⾓⾯对⾓线
if((Box[0][0][0]==Box[1][1][1])&&(Box[1][1][1]==Box[2][2][2]))
total++;
if((Box[0][0][2]==Box[1][1][1])&&(Box[1][1][1]==Box[2][2][0]))
total++;
if((Box[0][2][2]==Box[1][1][1])&&(Box[1][1][1]==Box[1][0][0]))
total++;
if((Box[0][2][0]==Box[1][1][1])&&(Box[1][1][1]==Box[0][1][1]))
total++;
//-----------------------------------------------------------------------------------------------------------//共49条对⾓线return total;
}
int seek(int n,int &whitenumber,int &blacknumber)
{
int i=n/9,j=(n/3)%3,k=n%3;
//if((blacknumber>0)&&(whitenumber>0))
// {
for(int value=black;value<=white;value++)
{
Box[i][j][k]=value;
//cout<
if(value==black)
blacknumber--;
if(value==white)
whitenumber--;
//n++;
if((whitenumber<0)||(blacknumber<0))
{
if(Box[i][j][k]==0)
blacknumber++;
else whitenumber++;
//n--;
continue;
}
if(n==26)
{
//cout<<"\n";
min=Min(test(),min);
//if(min==4)
//{
// for(int i=0;i<=26;i++)
// cout<
///<<"\n----------------------------------------\n";
//}
n--;
if(Box[i][j][k]==0)
blacknumber++;
else whitenumber++;
return 1;
}
n++;
seek(n,whitenumber,blacknumber);
if(Box[i][j][k]==0)
blacknumber++;
else whitenumber++;
//return 1;
}
n--;
return 1;
}
int main()
{
int n=0,whitenumber=13,blacknumber=14; seek(n,whitenumber,blacknumber);
cout<<"单⼀⾊球的线数最少为"<
return 1;
}
运⾏结果:
结果分析:
程序中有个关键:就是递归运⽤,由于⼀共有2^27种可能,所以尽量加些判断,直接减少那些不可能的情况,来提⾼程序效率。

通过本次试验,对数学建模有了更为深刻的认识,并且是分析问题和解决问题的能⼒提⾼了很多,令我获益匪浅并且感触良深。

相关文档
最新文档