数学模型及其在信息学竞赛中的应用.docx

上传人:b****4 文档编号:5529600 上传时间:2022-12-18 格式:DOCX 页数:12 大小:95.57KB
下载 相关 举报
数学模型及其在信息学竞赛中的应用.docx_第1页
第1页 / 共12页
数学模型及其在信息学竞赛中的应用.docx_第2页
第2页 / 共12页
数学模型及其在信息学竞赛中的应用.docx_第3页
第3页 / 共12页
数学模型及其在信息学竞赛中的应用.docx_第4页
第4页 / 共12页
数学模型及其在信息学竞赛中的应用.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

数学模型及其在信息学竞赛中的应用.docx

《数学模型及其在信息学竞赛中的应用.docx》由会员分享,可在线阅读,更多相关《数学模型及其在信息学竞赛中的应用.docx(12页珍藏版)》请在冰豆网上搜索。

数学模型及其在信息学竞赛中的应用.docx

数学模型及其在信息学竞赛中的应用

数学模型及其在信息学竞赛中的应用

 

【关键字】

数学模型,可靠性,可解性

【引言】

数学模型是人们解决现实问题的有力武器。

人们把现实问题经过科学地抽象、提炼得到数学模型,再用数学方法去解决。

数学模型可分为离散和连续两种。

连续数学模型需要大量的高等数学知识,中学生很少接触。

在信息学竞赛经常出现的则是离散数学模型。

本文主要介绍的就是离散数学模型的一般概念及建立方法。

【正文】

所谓数学模型,就是现实世界中某一类特殊的运动变化过程、关系或结构的一种模拟性的数学结构,其实也就是对现实模型进行科学抽象后得到的模型。

在信息学竞赛中,试题给出的问题通常是一个现实问题,这也就需要选手在审清题意后首先把问题的关键因素总结、提炼出来,形成一个抽象的数学模型,这样有利于问题的分析与解决。

一般来说,我们在解一道有关现实问题的试题时,需要分以下几个步骤:

1.审清题意,了解题目的来龙去脉,弄清哪些量是已知的(输入),需要求什么(输出),数据规模如何等等。

这是解决问题的前提。

2.建立模型,使之能够简洁高效地表达出题目给出的现实模型。

3.解决模型,得出算法。

建模之后就是要解决模型。

这步顺利与否很大部分上取决于所建模型的可解性如何。

4.编程实现。

其中,2、3两步是关键。

模型建立与解决得好与坏对能否成功解决该题起着决定性的作用。

(一)对于同一个现实问题,可能可以建立不同的数学模型

这种现象十分普遍,也就是平时所说的一题多解。

既然如此,这里有必要讨论一下数学模型的选择问题,其实也就是评判一个模型好坏标准的问题。

一个好的数学模型不仅要能够准确地反映出现实模型(可靠性),所建立的模型还必须能够被有效地解决(可解性)。

这里“有效”指的是解决它的算法所需的空间与时间都在可以承受的范围之内。

通常在解一些要求最优解或要求准确计数的一类具有唯一正确解的试题时,我们一般在保证可靠性的前提下,尽量提高模型的可解性。

若几个模型都具有可靠性,则当然可解性越强的模型越好。

例:

最佳旅行路线问题[IOI’93]

【问题描述】你在加拿大航空公司组织的一次竞赛中获奖,奖品是一张免费机票,可在加拿大旅行,从最西的一个城市出发,单方向从西向东经若干城市到达最东的一个城市(必须到达最东的城市);然后再单方向从东向西飞回起点(可途径若干城市)。

除起点城市外,任何城市只能访问1次,起点城市被访问2次:

出发一次;返回一次。

除指定的航线外,不允许乘其他航线也不允许使用其他交通工具。

求解的问题是:

给定城市表列及两城市之间的直通航线表列,请找出一条旅行路线,在满足上述限制条件下,使访问的城市数尽可能多。

这是一个现实问题,我们首先可以做如下的抽象:

把每个城市抽象成一个顶点。

不妨设由西到东的城市对应编号分别是1至n。

若两个城市之间有直通航线,则在相应的两点之间连一条边。

这样,所有城市与直通航线就被抽象成了一个无向图。

【盲目搜索】这是最原始的想法。

我们一开始假想有两架飞机都从最西边的城市飞向最东边的城市,并且在搜索的过程中保证两条路线中的城市除起点与终点外都不相同。

记下所有找到的路线中所经城市最多的方案,把其中的一条作为向东旅行的路线,一条作为向西旅行的路线,合并起来即得最佳旅行路线。

因为搜索的时间复杂度是指数级的,所以这样做的话,时间效率不够理想。

究其主要原因就是所有模型的抽象程度不够,没有把试题中的限制充分融入数学模型中,盲目性太大。

【网络流模型】为了把更多的试题中的限制融入模型中,我们在原有的模型的基础上建立了如下的最大费用最大流的模型:

1)为了保证每个城市最多只能被访问一次,我们把每个城市i拆成两个顶点i和i’,并在两个顶点之间连接一条i至i’的有向弧,单位费用设为0。

2)将原图中的无向边改为有向弧:

若城市i到城市j有直通航线(i

这样使得我们能够简单地从流量费用算出旅行路线上经过的城市数。

3)顶点1与1’,n与n’之间的弧的容量为2。

至此,本题的数学模型已经建立,试题给出的限制条件已体现在数学模型中,因此由此模型得出的解是可行的。

我们求从1到n’的最大费用最大流。

若得到的最大流量不是2,则无解(即不可能从西飞到东再飞回来),否则我们设得到的最大费用为C。

因为有两条路线,所以每个未被访问的城市在费用中的贡献为2,被访问的城市的贡献为3。

考虑到最西最东两个城市的贡献是2而不是3,旅行路线中访问城市数=C+2-2*N。

因为C最大,所以访问城市数也一定最多,即方案最佳,模型具有可靠性。

因为这是一个最大费用最大流的问题,我们可以使用Ford-Fulkerson算法去解。

这个模型与搜索相比,可解性大大提高,时间复杂度从指数级降低到了多项式级(大约为O(N^3))。

但我们还是觉得这个模型不够简洁,抽象程度还是不够。

【动态规则模型】设f[i,j]为从顶点1出发的两条不相交的路线分别到达顶点i与顶点j时,两路线的所需乘航线之和的最大值。

有两种情况,若i>j,或i=j=n时,我们考虑i的前趋顶点,不妨设为k。

此时,到达顶点k与j的两条路线的所需乘航线之和也一定最大,否则与f[i,j]最大矛盾。

若i

由此,我们有如下的动态规则方程:

f[i,i]无意义(1

实际最多可能的访问城市数为f[n,n]-2。

时间复杂度降为O(N^2)。

对于最佳旅行路线这一个问题,我们建立了三种不同的数学模型。

这三种模型都具有可靠性(可以得出最优解),但可解性不同。

一般来说,建立的模型越简洁,抽象程度越高,算法实现时不必要的操作也越少,运行效率也就越高。

值得注意的是,最近的一些竞赛中有时会出现根据解的近似程度给分的题目。

对于这类题目,我们更多考虑的则是所建模型的可解性。

当然,可靠性的降低也是有限度的,这个限度就是方案的可行性及误差允许范围。

此外,许多数学模型有近似解法,这些都是通过适当牺牲模型自身可靠性来提高模型的可解性。

(二)一个模型可能同时适用于多个现实问题。

这也就是我们要研究数学模型的主要原因之一。

我们解决一个数学模型就相当于解决了一类问题。

比如说,最短路径问题,可谓在现实生活中无处不在,上文中提到的网络流的模型也有着很高的实用价值。

这些数学模型的解决使得许多实际问题迎刃而解。

然而,数学模型的解决只是解决一个现实问题的一半,另一半就是如何将现实问题转化为一个已经解决的数学模型,即如何建模。

建模在现实与抽象之间起着桥梁的作用。

尤其在竞赛中,后者有时显得更为重要。

(三)如何建立数学模型?

要能够建立数学模型,首先必须熟悉一些经典的数学模型及其算法。

这是建模的基础,没有这个基础则根本谈不上建立什么数学模型。

竞赛中许多问题最终都可以转化为经典的数学模型,因此必须掌握这些常见的模型。

其次建立数学模型需要选手有把实际问题相互联系,类比的能力。

上文已经指出许多实际模型都有着相同或相似的数学模型。

既然这样,它们之间必然存在着一些相同或相似。

相互联系、类比是发掘这些信息的有效手段。

这里先给出一个大家都很熟悉的模型:

【凸n边形分割】一个凸n边形,可以通过不相交的(n-3)根对角线,把n边形拆分成(n-2)个三角形。

求方案数hn。

当n=5时,方案数h5=5。

【配对括号序列】求由n个左括号‘(’,n个右括号‘)’,能组成多少种不同的配对括号序列,记作Qn。

一个序列的配对与否定义如下:

1.()是配对的。

2.若A是配对的,则(A)也是配对的。

3.若A、B都是配对的,则AB也是配对的。

这两题的模型都是大家十分熟悉的Catalan数Cn=1/(n+1)*C(2n,n)。

通过数学计算可知,hn=Cn-2,Qn=Cn(证明略)。

【结和律】有n个数a1,a2,a3,…,an依据加法结合律,不改变其顺序,只用括号表示成对的和,问有几种求和方案Pn?

因为题目只要求求配对方案数,与a1,a2,a3,…,an的值无关。

我们不妨令S=a1+a2+a3+…+an,并把ai(0<=i<=n)当成矢量(矢量加法也有结合律)。

如下图。

这样本题的方案与上题的方案就建立了一一对应的关系,本题的结果也就可以很容易地用Catalan数表示出来。

Pn=hn+1=Cn-1。

【二叉树计数】问有n个结点的二叉树共有几种?

本题其实可以与【配对括号序列】联系。

考虑从根结点开始中序遍历一个二叉树的过程。

每当第一次到达一个结点时,将该结点压栈,记作‘(’,并开始递归访问其左子树;返回时访问该结点,并将该结点出栈,记作‘)’,再递归访问其右子树。

这样一个二叉树就对应与一个配对的括号序列。

反过来,根据任何一个配对的括号序列,我们都可以画出与其惟一对应的二叉树(证明略)。

这样一来,每个结点都要出入栈一次,所以序列中一共有n对括号。

即n个结点的二叉树共有Qn=Cn种。

类似的问题还有许多,比如说【碗摞问题】,【排队找零问题】等等,这里就不再赘述。

它们都是一些表面上看上去不同,本质却相同的问题。

我们可以通过在它们之间相互联系、类比,得到一个经典的Catalan数的模型。

信息学竞赛不只是编程的竞赛,更是智力的竞赛。

创造力是智力很重要的一方面。

数学建模没有固定模式,能够很大程度上体现出选手的创造力,因此深受信息学竞赛的青睐。

随着信息学竞赛的不断发展,题目中数学模型越来越隐蔽,对选手的创造力要求也越来越高。

例:

01串[NOI99]

【题目描述】寻找一个全有0或1组成且长度为N字符串并使得其中

●任意连续L0个字符中的0的个数不小于A0不大于B0,

●任意连续L1个字符中的1的个数不小于A1不大于B1。

若不存在这样的01串,则输出-1,否则输出其中一个串。

数据范围:

N≤1000

这道题目的数学模型非常隐蔽。

许多选手当时使用了盲目搜索。

由于字符串长度最大可达1000,每一位可以是’0’或’1’两种情况,盲目搜索的最坏时间趋近于2^1000,十分恐怖,运行时间也就可想而知了。

即使有限的约束条件也改变不了搜索效率低下的本质。

其实,本题是用图论模型来解竞赛题的成功之作。

在解本题之前,我们先来看另一道题:

例:

BlackandWhite[CEOI’94]

【题目描述】寻找一个由n个整数组成的数列,其中任意连续p个整数之和为正,任意连续q个整数之和为负。

若不存在这样的整数数列,则输出NO,否则输出其中一个数列。

本题数学模型建立的关键在于连续数之和的表示。

如果我们把紧跟在第i个整数之后的k个整数写作ai+1+ai+2+…+ai+k的话,数学模型就很难建立了,因为这里涉及k个整数之和。

但是,我们可以利用连续这一特点,将其表示为Si+k-Si,这样的表示就十分简单,使得数学模型的建立相对容易些。

我们记Si为数列中前i个整数之和,S0=0。

根据题意,可以列出如下两组不等式:

Si>Si-p(p≤i≤n)

Si

 

我们再建一个有向图,共有n+1个顶点,分别是S0至Sn,若Si

如图(n=6,p=5,q=3)。

这样对于S0,S1,…,Sn来说,他们必须是拓扑有序的(S0=0),反过来,任何一组S0…Sn都惟一地对应一个整数数列。

现在,我们已经把这道题目轮换为一个图论的拓扑排序的问题,而这个问题又是我们非常熟悉的。

程序见附录。

回到NOI’99的那道题,将此题与CEOI’94的那题相互联系,我们发觉这两题都涉及到连续这个概念。

我们也同样可以建一个图,顶点分别表示S0…Sn,这里Sn表示所求串第i位以前(包括第i位)’1’的出现次数。

略有不同的是,这次不但Si与Sj之间有大小关系,还需要表示出到底大多少。

我们把这个量作为Si与Sj之间的边上的权。

具体地说,若Sj≥Si+k,则我们就从Si向Sj引一条权为k的单向边。

至此,题目中的两个条件都已经在图中体现出来了。

还有一点需要注意的是,本题与上题不同,它要求每个字符非’0’即’1’,所以我们也需要把这点体现在图中,即再加2n个不等式:

Si+1≥Si,Si+1≤Si+1。

接下来的问题就是求其它各点到S0的最长路。

其实,本题与上题都可以转化为同一个模型,即图论最长路问题,因为我们可以把上题图中边的权就看作是1。

初看上去,以上两题都似乎与图论无甚关系。

题目中并没有出现图论中常见的“城市”,“终端”等顶点,也没有“铁路”,“线路”等边,还没有“长度”,“传输时间”等权,但都确确实实用图论模型漂亮地解决了,不由地让人发出感叹――真没想到呀!

其实,想到与没想到虽就一念之差,却不是偶然的:

这里面既有经验的因素,也与你所掌握数学模型的多少有关,更重要的则是你的创造力。

在上两题中把Si作为顶点,大小关系作为边,以及权的确定都不可以不说是一种创造。

而正是它们在上两题的解决中起了关键性的作用。

纵观人类的进步史,创造力有着举足轻重的作用。

计算机发展至今,无论是性能的提高,软件的发展,还是网络的诞生,处处体现了人类非凡的创造力。

创造力是研究信息学的基本素质之一,也是信息学竞赛考察的重点。

【参考书目】

青少年国际和全国信息学(计算机)奥林匹克竞赛指导丛书

――组合数学的算法与程序设计吴文虎、王建德编著

――图论的算法与程序设计吴文虎、王建德编著

清华大学出版社

数学模型基础王树禾编著

中国科学技术大学出版社

【附程序】

BlackandWhite,CEOI94:

{$A+,B-,D-,E-,F-,G+,I-,l-,N-,O-,P-,Q-,R-,S-,T-,V-,X-}

{$M65520,0,655360}

programBlack_and_White(input,output);

const

maxn=1000;

var

i,n,p,q,count:

integer;{count:

拓朴排序的序号}

s,d:

array[0..maxn]ofinteger;{d[i]为顶点i的入度}

next:

boolean;{拓朴排序结束标记}

begin

write('n,p,q=');

readln(n,p,q);

{计算入度}

fillchar(d,sizeof(d),0);

fori:

=0tondo

begin

ifi+p<=ntheninc(d[i+p]);{S(i)

ifi-q>=0theninc(d[i-q]);{S(i)

end;

{拓朴排序}

count:

=0;

repeat

next:

=false;

fori:

=0tondo

ifd[i]=0then

begin

s[i]:

=count;

inc(count);

ifi+p<=nthendec(d[i+p]);{相邻顶点入度减1}

ifi-q>=0thendec(d[i-q]);

d[i]:

=-1;

next:

=true;

end;

untilnotnextor(count=n+1);{直到所有顶点已被赋上序号或无0度顶点为止}

{输出}

ifcount<>n+1then{存在环}

writeln('NO')

else

fori:

=1tondowriteln(s[i]-s[i-1]);

end.

01串,NOI99:

{$A+,B-,D-,E-,F-,G+,I-,l-,N-,O-,P-,Q-,R-,S-,T-,V-,X-}

{$M65520,0,655360}

programsequence(input,output);

const

inputfile='input.txt';{输入文件名串}

outputfile='output.txt';{输出文件名串}

var

head:

array[0..1000,1..6]ofrecord{有向图。

head[i,k]—顶点k引出的第k条有向边,其中}

no,v:

integer;{head[i,k].no为该边的终点序号;head[i,k].v为该边的权}

end;

num:

array[0..1000]ofshortint;{num[i]—顶点i引出的边数}

s:

array[0..1000]ofinteger;{s[i]—0位‥i位中1的个数}

n,a0,b0,l0,a1,b1,l1:

integer;{n—串长;l0,a0,b0—连续长度为l0的子串中,0的个数的下限和上限为a0、b0;l1,a1,b1—连续长度为l1的子串中,1的个数的下限和上限为a1、b1}

procedureaddedge(a,b,c:

integer);{从顶点a出发,构造一条权为c的有向边}

begin

inc(num[a]);{累计顶点a引出的边数}

head[a,num[a]].no:

=b;{设置该边的终点和权}

head[a,num[a]].v:

=c;

end;{addedge}

procedureinit;{输入数据,构造有向图head}

vari:

integer;

begin

readln(n,a0,b0,l0,a1,b1,l1);{输入数据}

fillchar(head,sizeof(head),0);{有向图初始化}

fori:

=1tondobegin{逐个顶点地构造有向图}

ifi>=l0thenbegin{根据a0≤l0-(si-

)≤b0构造有向边}

addedge(i,i-l0,a0-l0);

addedge(i-l0,i,l0-b0);

end;{then}

ifi>=l1thenbegin{根据a1≤si-

≤b1构造有向边}

addedge(i-l1,i,a1);

addedge(i,i-l1,-b1);

end;{then}

addedge(i-1,i,0);{根据si-1≤si构造有向边}

addedge(i,i-1,-1);{根据si≤si-1+1构造有向边}

end;{for}

end;{init}

proceduremain;{计算顶点0至其余顶点的最长路径}

vari,j,k:

integer;

begin

fillchar(s,sizeof(s),0);{s数组清零}

fori:

=1tondo{逐条边地延长路径}

forj:

=0tondo{枚举第i条边的所有可能情况}

fork:

=1tonum[j]do

ifs[j]+head[j,k].v>s[head[j,k].no]{若顶点0至顶点head[j,k].no的所有路径中,经过顶点j的第k条有向边的一条路径为目前最长,则记下}

thenbegin

s[head[j,k].no]:

=s[j]+head[j,k].v;

ifs[head[j,k].no]>head[j,k].nothenbegin

{若0位‥head[j,k].no位全填1也不能满足条件,则无解退出}

writeln(-1);

exit;

end;{then}

end;{then}

forj:

=0tondo{检查有向图。

若出现有向环,则无解退出}

fork:

=1tonum[j]do

ifs[j]+head[j,k].v>s[head[j,k].no]thenbegin

writeln(-1);

exit;

end;{then}

fori:

=1tondo{根据s数组的值构造满足条件的01串}

ifs[i]=s[i-1]thenwrite(0)

elsewrite

(1);

writeln;

end;{main}

begin

assign(input,inputfile);{输入文件名串与文件变量连接}

reset(input);{输入文件读准备}

assign(output,outputfile);{输出文件名串与文件变量连接}

rewrite(output);{输出文件写准备}

init;{输入数据,构造有向图}

main;{计算和输出一个满足所有条件的01串}

close(input);{关闭输入文件和输出文件}

close(output);

end.{程序结束}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1