Olympiad in Informatics Beginners' Home's Archiver

zhiheng3 发表于 2008-11-17 10:35 PM

NOIP2008普及组题解

[i=s] 本帖最后由 zhiheng3 于 2008-11-21 09:12 PM 编辑 [/i]

这次普及组题目虽然称不上很难,但都比较难懂,第四题也是比较麻烦。正在练习写解题报告,不足之处也请大家指出,代码附在附件中,已经经过测试

第一题:很水的送分题,可能对于刚刚接触OI的选手来说,处理字符串是一个难点,不妨用整体读入,用st-'0'[fly]的方法即可求出该位数字(C++写法,PASCAL有些忘记见谅,希望有人能够补充上)。最后注意'X'即可获得满分


第二题:贪心。该题的难点是读懂题意,其实只需记录将第几行第几列隔开可以阻止多少对学生说话,最后进行两次排序(一次为了求出可以阻止最多对数说话的行或列,一次为了按顺序输出),输出即可。注意行尾不能有空格


第三题:动态规划or记忆化搜索,我的代码是用记忆化搜索写的,动态规划方程为:f[j]=f[i+1][j-1]+f[i-1][j-1](i表示当前球在人的号码,j表示经多少次传回小蛮手中,注意边界条件及i的循环性即可。用记忆化搜索则需要注意无解情况,避免死循环


第四题:比较繁琐的一道题,但其实只要分析清楚题意,还是很容易解出的。
          第一步:将基本图形存到数组中
          第二步:算出每个立方体左上角的坐标
          第三步:按从后向前,从下向上,从左向右的顺序依次覆盖输出数组,最后数组内存的即为最后答案(覆盖前将数组初始化为'.')

PASCAL代码已经贴出,感谢oimaster提供代码

请大家加入OI交流群74762057,有很多NOI,IOI,集训队大牛加入此群

如果有不正确或不明确的地方,欢迎大家予以指正。欢迎大家加我的QQ:409137693,如果是初学者我愿意帮忙,如果是大牛就请允许我讨教~~~~~~

[BOT]rellik6 发表于 2008-11-17 10:37 PM

完整题目贴一下好吗?

zhiheng3 发表于 2008-11-17 10:39 PM

不好意思,卷子被老师收走了,等我上网找一下再发布

[BOT]rellik6 发表于 2008-11-17 10:40 PM

...............网上找不到啊..............

zhiheng3 发表于 2008-11-17 10:41 PM

那现在没有办法,不好意思,过两天应该会有人发布的

zhiheng3 发表于 2008-11-18 09:19 PM

希望能有人贴一下PASCAL的代码,毕竟PASCAL还是多数

子夜长河 发表于 2008-11-18 09:20 PM

不错,看一下自己的方法有哪些不足

zhiheng3 发表于 2008-11-18 09:56 PM

希望大家都多提一点自己的想法,给更多的人思路,毕竟大牛都是从初学者过来的

oimaster 发表于 2008-11-19 05:41 PM

[i=s] 本帖最后由 oimaster 于 2008-11-19 08:34 PM 编辑 [/i]

第三题还可以这样做:
每一种传法就是一串长度为m的01串,因为往左传和往右传可以抵消,所以0和1个数差应该是n的倍数才能传回原点。穷举0的个数a,得到1的个数b(m-a),验证abs(a-b)是否是n的倍数,如果是,就在总数上加C(m,a)。
程序:[code] program ball(input,output);
var
  n,m,a,b:integer;
  total:longint;
  f:array[0..30,0..30] of longint;

function c(n,r:integer):longint;
  begin
    if r>n then exit(0);
    if r=0 then exit(1);
    if f[n,r]<>0 then exit(f[n,r]);
    c:=c(n-1,r)+c(n-1,r-1);
    f[n,r]:=c;
  end;

begin
  assign(input,'ball.in');
  reset(input);
  readln(n,m);
  close(input);
  fillchar(f,sizeof(f),0);
  total:=0;
  for a:=0 to m do
    begin
      b:=m-a;
      if (b-a) mod n=0 then
        total:=total+c(m,a);
    end;
  assign(output,'ball.out');
  rewrite(output);
  writeln(total);
  close(output);
end.

[/code]

woshi4gezhu 发表于 2008-11-19 06:47 PM

有pascal的么?

zhiheng3 发表于 2008-11-19 07:37 PM

9楼的代码一会我测试一下,想法很好
LS的,我有时间会把我的程序翻译成PASCAL,不过速度会有点慢,很长时间不用了~~

[BOT]rellik6 发表于 2008-11-19 08:09 PM

var
  n,m,i,j:longint;
  f:array [0..30,0..30] of longint;
begin
  assign(input,'ball.in');
  reset(input);
  assign(output,'ball.out');
  rewrite(output);
  read(n,m);
  fillchar(f,sizeof(f),0);
  f[0,1]:=1;
  for i:=1 to m do
  begin
    f[i,1]:=f[i-1,n]+f[i-1,2];
    for j:=2 to n-1 do f[i,j]:=f[i-1,j-1]+f[i-1,j+1];
    f[i,n]:=f[i-1,n-1]+f[i-1,1]
  end;
  writeln(f[m,1]);
  close(input);
  close(output)
end.

qiyycc 发表于 2008-11-19 08:26 PM

谢谢楼主了!
第一题就因为没看题挂了……

oimaster 发表于 2008-11-19 08:29 PM

第一题
[code]program isbn(input,output);
var
  i,code,t,sum,n:longint;
  str:string;
begin
  assign(input,'isbn.in');
  reset(input);
  readln(str);
  close(input);
  val(str[1],t,code);
  sum:=t;
  for i:=3 to 5 do
    begin
      val(str[i],t,code);
      sum:=sum+(i-1)*t;
    end;
  for i:=7 to 11 do
    begin
      val(str[i],t,code);
      sum:=sum+(i-2)*t;
    end;
  n:=sum mod 11;
  assign(output,'isbn.out');
  rewrite(output);
  if n<10 then
    if ord(str[13])=n+48 then
      writeln('Right')
    else
      begin
        str[13]:=chr(n+48);
        writeln(str);
      end
  else
    if str[13]='X' then
      writeln('Right')
    else
      begin
        str[13]:='X';
        writeln(str);
      end;
  close(output);
end.
[/code]

oimaster 发表于 2008-11-19 08:30 PM

[i=s] 本帖最后由 oimaster 于 2008-11-19 08:33 PM 编辑 [/i]

第二题:[code]program seat(input,output);
var
  hang,lie:array[1..1000] of longint;
  ans:array[1..2,1..1000] of boolean;
  m,n,k,l,d:longint;

function min(a,b:longint):longint;
  begin
    if a<b then exit(a) else exit(b);
  end;

procedure init;
  var
    i,x,y,p,q:longint;
  begin
    fillchar(lie,sizeof(lie),0);
    fillchar(hang,sizeof(hang),0);
    assign(input,'seat.in');
    reset(input);
    readln(m,n,k,l,d);
    for i:=1 to d do
      begin
        readln(x,y,p,q);
        if x=p then
          inc(lie[min(y,q)])
        else
          inc(hang[min(x,p)]);
      end;
    close(input);
  end;

procedure work;
  var
    i,j,max,no:longint;
  begin
    fillchar(ans,sizeof(ans),false);
    for i:=1 to k do
      begin
        max:=0;
        no:=0;
        for j:=1 to m-1 do
          if (not ans[1,j]) and (hang[j]>=max) then
            begin
              max:=hang[j];
              no:=j;
            end;
        ans[1,no]:=true;
      end;
    for i:=1 to l do
      begin
        max:=0;
        no:=0;
        for j:=1 to n-1 do
          if (not ans[2,j]) and (lie[j]>=max) then
            begin
              max:=lie[j];
              no:=j;
            end;
        ans[2,no]:=true;
      end;
  end;

procedure print;
  var
    temp:array[1..1000] of integer;
    i,total:longint;
  begin
    assign(output,'seat.out');
    rewrite(output);
    total:=0;
    for i:=1 to m-1 do
      if ans[1,i] then
        begin
          inc(total);
          temp[total]:=i;
        end;
    for i:=1 to total do
      if i<total then
        write(temp,' ')
      else
        writeln(temp);
    total:=0;
    for i:=1 to n-1 do
      if ans[2,i] then
        begin
          inc(total);
          temp[total]:=i;
        end;
    for i:=1 to total do
      if i<total then
        write(temp,' ')
      else
        writeln(temp);
    close(output);
  end;

begin
  init;
  work;
  print;
end.
[/code]

zhiheng3 发表于 2008-11-19 08:32 PM

呵呵,谢谢LS以及LS的LS的LS贴出的代码,我会整理到一起做为附件供大家下载,欢迎大家加入OI交流群74762057,我正准备邀请各位IOI,NOI各位大牛加入

oimaster 发表于 2008-11-19 08:33 PM

第四题:
[code]program drawing(input,output);
const
  t:array[1..6,1..7] of char
   =(('.','.','+','-','-','-','+'),
     ('.','/',' ',' ',' ','/','|'),
     ('+','-','-','-','+',' ','|'),
     ('|',' ',' ',' ','|',' ','+'),
     ('|',' ',' ',' ','|','/','.'),
     ('+','-','-','-','+','.','.'));
var
  ans:array[1..500,1..500] of char;
  a:array[1..50,1..50] of integer;
  m,n:integer;

procedure init;
  var
    i,j:integer;
  begin
    assign(input,'drawing.in');
    reset(input);
    readln(m,n);
    for i:=1 to m do
      for j:=1 to n do
        read(a[i,j]);
    close(input);
  end;

procedure work;
  var
    i,j,k,t1,t2,x,y:integer;
  begin
    fillchar(ans,sizeof(ans),46);
    for i:=1 to m do
      for j:=1 to n do
        for k:=1 to a[i,j] do
          begin
            t1:=495-(m-i)*2-(k-1)*3;
            t2:=4*j-3+(m-i)*2;
            for x:=1 to 6 do
              for y:=1 to 7 do
                if t[x,y]<>'.' then ans[t1+x-1,t2+y-1]:=t[x,y];
          end;
  end;

procedure print;
  var
    i,h,sum,j:integer;
  begin
    h:=1;
    while true do
      begin
        sum:=0;
        for i:=1 to 500 do
          if ans[h,i]='.' then inc(sum);
        if sum<500 then break;
        inc(h);
      end;
    assign(output,'drawing.out');
    rewrite(output);
    for i:=h to 500 do
      begin
        for j:=1 to 4*n+2*m+1 do
          write(ans[i,j]);
        writeln;
      end;
    close(output);
  end;

begin
  init;
  work;
  print;
end.
[/code]

zhiheng3 发表于 2008-11-19 08:50 PM

那个~~~LS的朋友,先谢谢,然后请你看一下第二题我不能编译,修改一下,我这里Free Pascal不好用,谢谢,其他3题均通过测试,准确无误

zhiheng3 发表于 2008-11-20 07:35 PM

PASCAL代码已经贴出,感谢oimaster提供代码

loveloveyjl 发表于 2008-11-21 03:50 PM

倒霉呀
我如果再细心一点就是吉林省的第一名了
感谢大家给的第三题的解题报告

页: [1] 2


Powered by Discuz! Archiver 7.0.0  © 2001-2009 Comsenz Inc.