程序设计中的基本算法(修改)
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
关系式求值,如果为“True”的表达式有3个那么这时“thisman”的值就是
问题的解。
已知的证词可以表示为:
“证词表述”
证词
语句表示
A说:不是我
Thisman<>’A’;
B说:是C
Thisman=‘C’;
C说:是D
Thisman=‘D’;
D说:他胡说
Thisman<>’D’;
program exp1_3;
a[i]:=a[i] div 2 + q div 2 接下来判断这时a[i]是否是奇数,如果是奇 数,教师再给他一个糖果并计数,重复上面的过 程直到每人手里的糖果数相等。
枚举法
枚举法解决问题的基本思路是依次枚举问题的所以可
能解,按照问题的约束条件进行判断,如果满足约束条件
则得到一组解,这个过程不断的进行下去最终得到整个问
题的解。可以说模拟法主要关心问题“怎么做”,枚举法
主要关心当前的可能解“是不是”。
要用枚举法解决问题,首先需要知道解的范围并能以
合适的方法列举,其次要对问题的约束条件进行精确的描
述,这两个环节有一个疏漏就有可能丢失正确解或多出错
误解。枚举法虽然实现起来很容易,但对于大数据量的枚
举效率是很低的。
例题3:四人中有一人是小偷,现在警察得到了这样的证词:
A说:不是我。
B说:是C。
C说:是D。
D说:他胡说。
已知3个人说的是真话,一个人说的是假话。现在要根据这些信息,
确认小偷是谁。
【问题分析】:
假设小偷是“thisman”,由于“thisman”的取值无非是‘A’、‘B’、
‘C’、‘D’,如果我们让“thisman”的取值依次是‘A’~‘D’,分别对4个
程序要求:根据输入的边长之和P,输出所有满足上述条件的三角形 的个数及方案。
【问题分析】:
按题意直接直接枚举就行。注意利用每个数之间的大小关系。在
检测是用一个数组保存出现的数字,检测数组第1~9个元素就可以分
辨1~9这9个数字是否不重复的出现。
program exp2_3;
var
fillchar(a,sizeof(a),true);
for j:=1 to n do
for k:=1 to n do
if k mod j=0
then a[k]:=not a[k];
s:=0;
for j:=1 to n do {统计个数}
if a[j]=false then inc(s);
一个好的算法,占用空间小,运行时间短, 计算机科学家和程序设计员一直在追求更 高效的算法。
模拟法
有些问题的描述和解决方法已经很清楚,只需要 按照描述去一步一步的执行即可,这种方法就是 计算机解决问题的一种最普遍最直接的方法—模 拟法。模拟法并不是算法,它只是我们依赖计算 机的运算速度解决问题的一种方法或模式,针对 具体问题设计具体的程序。
for f:=a+1 to 8 do
for i:=f+1 to 9 do
begin
d:=p-a-b-f;
if d<=b then break;
h:=p-f-g-i;
if h<=g then break;
e:=p-a-c-i;
if e<=c then break;
fillchar(bb,sizeof(bb),0);
来求另一组解,所以求解过程中可仅考虑a1<a2<a3<a4<a5<a6<a7的情况。
很显然要使1,28两种刻度能量出来,则在7个刻度中就必须有1或28;
这样就可以设a1=1(或a1=28)。题解就变成了在2—27中选取6个刻度的
问题了。其刻度数目为C626=230230。
这样解的范围就从百万数量级变成了十万的数量级,大大减少了运
var
n:integer;
t:char;
begin
for t:='A' to 'D' do
begin
n:=ord(t<>’A’)+ord(t=‘C’)+ord(t=‘D’)+ord(t<>’D’);
if n=3 then writeln('thisman is ',t);
for a[5]:=a[4]+1 to n-4 do
for a[6]:=a[5]+1 to n-3 do
for a[7]:=a[6]+1 to n-2 do
begin
for i:=1 to 29 do b[i]:=0;
for i:=1 to 7 do
begin
b[a[i]]:=1;b[n-a[i]]:=1;b[n]:=1; {初始化}
6
a6, a6﹣a1, a6﹣a2, a6﹣a3, a6﹣a4, a6﹣a5, 29﹣a6
7
a7, a7﹣a1, a7﹣a2, a7﹣a3, a7﹣a4, a7﹣a5, a7﹣a6, 29﹣a7 8
可量出2+3+4+5+6+7+8种刻度,即35种刻度。事实上期中有许多刻度 是重复的,不可能覆盖1—29。例如:a1,a2,a3,a4,a5,a6,a7为1,3,6, 10,15,21,28时,能量出的可度为:
分发糖果?一些学生围绕老师座着每人手里都有偶数个糖果现在老师吹一声哨子所有学生同时将自己的一半糖果给他右边的同学如果某个同学手里的糖果个数是奇数则老师给他一个糖果
程序设计中的基本算法
什么是算法?
简单来说算法是解决问题的方法和步骤, 它不是问题的答案,但它是经过准确定义 的,用来获得答案的过程。
模拟法适用于问题求解清晰,运算规模较小的问 题,如果问题求解的时空代价很大就要考虑是否 有其它更优的解决方案。
例题1:酗酒的狱警
某监狱里有个很长的走廊,走廊中一个接一个有n个房间。每个房间中 锁着一个犯人。一天夜里,狱警决定玩一个无聊游戏。第一轮中,他喝 了一口威士忌,然后打开走廊间每个房子。第2轮,他喝了一口威士忌, 然后按2的倍数遍历每个房子,第3轮,他又喝了一口威士忌,遍历所 有3的倍数的房间,依次类推。在遍历中,如果房间是锁的,则打开 否则锁上。他这样重复n轮,最终醉酒。这时有些囚犯人看到自己房间 的所以打开,他们立即逃跑。对于有n间房子的走廊,最终会有多少 囚犯逃脱。
出来。例如选择的刻度为:a1,a2,a3,a4,a5,a6,a7那么能量出的刻度为:
a1, 29﹣a1
2
a2, a2﹣a1, 29﹣a2
3
a3, a3﹣a1, a3﹣a2, 29﹣a3
4
a4, a4﹣a1, a4﹣a2, a4﹣a3, 29﹣a4
5
a5, a5﹣a1, a5﹣a2, a5﹣a3, a5﹣a4, 29﹣a5
for j:=i+1 to 7 do b[abs(a[j]-a[i])]:=1
end;
j:=0;
for i:=1 to n do gin
for i:=1 to 7 do write(a[i]:4);
writeln
end;
end;
end.
输入:第一行中输入一个整数表示有多少组测试数据。接下来的若干 行,每行包含一个5至100整数,这是房间的数目,输出:对应输入数 据输出多行,每行一个整数,表示逃脱的囚犯数量。
样例输入:
2
5
100
样例输出:
2
10
【问题分析】:
由于问题的规模较小,按照题意用一个200个元素的布尔型数组表示房间的状态, “true”表示房间门是关闭的,“false”表示房间门是开的。每次遍历数组,将当 前数到数的倍数元素的状态反转,最后遍历数组统计房间开着的个数输出。
6 36 2 2 2 2 2 11 22 20 18 16 14 12 10 8 6 4 2 4 2 4 6 8 0
样例输出:
15 14 17 22 48
【问题分析】: 首先判断每个人的糖果数是否相等,如果相
等则分配结束,否则开始重新分配过程。由于题 目中说明是同时将每人手里的糖果数的一半给右 边的人,而用程序实现时是逐句执行,因此若用 a[i]表示每人手里的糖果数,q表示第i-1位手中 的原糖果数,则有:
writeln(a:3,b:3,c:3,d:3,e:3,f:3,g:3,h:3,i:3);
end;
end;
writeln(sum);
end.
例题5:一根29cm长的尺子,只允许在上面刻7个刻度,要能用它量出 1—29cm的各种长度。试问这根尺子的刻度该怎么选择?
问题分析:
⑴从1—29cm中选择7个刻度的所有可能情况是C729 =1560780 ⑵对于每一组刻度的选择都需要判断是否能将1—29cm的各种刻度量
end;
end.
例题4: 数字三角形(NOIP1997普及组第2题)
把1,2,… 9共9个数排成下列形状的三角形:
a
bc
d
e
f ghi
其中:a~i分别表示1,2,...9中的一个数字,并要求同时满足
下列条件:
(1) a<f<i
(2)b<d, g<h, c<e;
(3)a+b+d+f= f+g+h+i= i+e+c+a= P
例题6:邮局发行一套四种面值的邮票,如果每封信所贴邮票张数不 超过3张,存在整数r,使得用不超过三枚的邮票,可以贴出连续的整 数1、2、3、…、r来,找出这四种面值邮票,使得r值最大。
问题分析:
本题与上题有相似之处,上题知道总长,搜索7个刻度,而本题则是 知道每封信邮票数的范围(<=3),邮票有四种面值,编程找出能使 连续面值最大的邮票。
结束后每人手里又有多少个糖果。
输入:
包含多组数据,每组数据的第一行是一个数字n,表示学生的个
数,下面的n行以顺时针次序,每行一个数字表示每个学生手里的糖
果个数,输入以学生个数为0结束。
输出:
对于每组数据输出一行包含两个数据,老师吹哨子的次数和学生
最后平均的糖果数,中间以空格相隔。
样例输入:
bb[a]:=1;bb[b]:=1;bb[c]:=1;bb[d]:=1;bb[e]:=1;bb[f]:=1;bb[g]:=1;bb[h]:=1;bb[i]:=1;
for k:=1 to 9 do
if bb[k]=0 then break;
if bb[k]=1 then
begin
inc(sum);
【程序实现】:
program exp1_1;
var
num,s,n,m,i,k,j:integer;
a:array[0..200] of boolean;
begin
readln(num); {读入测试数据的个数}
for i:=1 to num do
begin
readln(n); {读入房间数}
行次数。因此,我们在用穷举法求问题解时,应注意程序的优化,尽可 能减少搜索时间。
⑶为了判定7个刻度是否能够度量1—29的所有长度,可以用集合的方法, 也可以用数组的0,1数据判断。
program ex5_kedu;
const n=29; m=1;
var a:array[1..7] of integer;
writeln(s);
end;
end.
例题2:分发糖果
一些学生围绕老师座着,每人手里都有偶数个糖果,现在老师吹
一声哨子,所有学生同时将自己的一半糖果给他右边的同学,如果某
个同学手里的糖果个数是奇数则老师给他一个糖果。重复这个过程直
到所有同学手中的糖果数一致。
写一个程序判断老师要吹多少下哨子每人手中的糖果数才能一致,
b:array[1..n] of 0..1;
{记录能量的刻度}
f:boolean; i,j:integer;
begin
a[1]:=m;
for a[2]:=2 to n-7 do
for a[3]:=a[2]+1 to n-6 do
for a[4]:=a[3]+1 to n-5 do
1,28
3,2,26
6,5,3,23
10,9,7,4,19
15,14,12,9,5,14
21,20,18,15,11,6,8
28,27,25,22,18,13,7,1
缺16,17,24(29即尺子长度)
如果找出了刻度a1,a2,a3,a4,a5,a6,a7那么我们就可以利用对称性29-an
a,b,c,d,e,f,g,h,i,k,p,sum:integer;
bb:array[-100..100] of byte;
begin
readln(p);
sum:=0;
for a:=1 to 7 do
for b:=1 to 8 do
for c:=1 to 8 do
for g:=1 to 8 do