2025年05月01日 星期四 农历 乙巳年(蛇)四月初四

信息学奥赛常考算法——模拟法

发布人:钱翠萍    发布时间:2012-06-04 点击量:5956

模拟法

有些问题的描述和解决方法已经很清楚,只需要按照描述去一步一步的执行即可,这种方法就是计算机解决问题的一种最普遍最直接的方法------模拟法。

    模拟法并不是程序,只是我们依赖计算机的运算速度解决问题的一种方法或模式,针对具体问题要设计具体的程序。

    模拟法适用于问题求解清晰、运算规模较小的问题。如果问题求解的时空代价很大,就要考虑是否有其它更好的解决方案。

典型例题:

例题1、酗酒的狱警。某监狱里有个很长的走廊,走廊中一个接一个地有n个房间。每个房间中锁着一个犯人。一天夜里,狱警决定玩一个无聊的游戏。第一轮中,他喝了一口威士忌,然后打开每个房间。第2轮,他喝了一口威士忌,然后按2的倍数遍历每个房间。第3轮,他又喝了一口威士忌,遍历所有3的倍数的房间,以此类推。在遍历中,如果房间是锁着的,则打开;否则锁上。他这样重复n轮,最后醉酒。这时有些囚犯看到自己的房间所被打开了,他们立即逃跑。对于有n个房间的走廊,最终会有多少个囚犯逃脱?

程序:

program yujing;

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);

        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);

        writeln('the last is:',s);

    end;

end.

2、分发糖果。一些学生围绕老是坐着,每人手里都有偶数个糖。现在老师吹一声哨子,所有同学同时将自己的一半糖果给他右边的同学,如果某个同学手里的糖果个数是奇数,则老师给他一个糖果,重复这个过程直到所有同学手中的糖果数一致。

写一个程序判断老师要吹多少下哨子,每人手中的糖果数才能一致,并给出结束后每人手里的糖果数。

程序:

program fatang;
const maxn=100000;
type arr=array[0..maxn] of longint;
var a:arr;n,i,total,sum:longint;

procedure check(a:arr;n:longint);  {计算吹哨子次数和最终糖果数}
var i,p,q,j,k:longint;

function eq(a:arr;n:longint):boolean; {判断每人的糖果数是否相等}
var i:longint;
begin
  i:=1;
  while (i    inc(i);
  if i=n then eq:=true else eq:=false;
end;

begin
  while not eq(a,n) do  {
如果每人糖果不等,则继续分配}
  begin
    inc(total);    {
吹哨子数增加一次}
    q:=a[n];
    for i:=1 to n do   {
重新分配}
    begin
      p:=a[i];
      a[i]:=q div 2+a[i] div 2;
      q:=p;
      if odd(a[i]) then
      begin
        inc(a[i]);
        inc(sum);    {
如果是奇数,老师再给一个,并计数}
      end;
    end;
  end;
  writeln(total,' ',sum div n);
end;

begin
  readln(n);  {
读入学生人数}
  while n>0 do
  begin
    sum:=0;
    total:=0;
    for i:=1 to n do
    begin
      readln(a[i]);  {
读入每人的糖果数}
      inc(sum,a[i]);  {
计算糖果总数}
    end;
    check(a,n);  {
计算吹哨子的次数和糖果数}
    readln(n);
  end;
end.