• mine layer(2008 World Final C)


    类似于扫雷游戏,在一些格子中散布着一些地雷,具体的埋藏位置并不清楚,但知道每个格子及其周围八个格子的地雷总数。请问此时正中间那一行最多可能有多少地雷(题目假定所有的输入都是奇数行的)?

    输入:

       第一行,有一个正整数N,代表有N个测试数据。

       每个测试数据的第一行包含两个正整数R(行数,R是奇数)和C(列数)。以下是R行每行C列的正整数。

    输出:

      每个测试数据输出一行,“Case #X: Y”,x为第几个测试数据,Y为正中间那一行最多可能有的地雷数。

    限制条件

    输入有R行C列

    small

    R=3,5

    3≤C≤5

    Large

    3≤R≤49,R是奇数

    3≤C≤49

    样例1


    Input
     


    Output
     

    2
    3 3
    2 2 1
    3 4 3
    2 3 2
    3 4
    1 2 1 1
    2 3 3 2
    2 2 2 1

    Case #1: 1
    Case #2: 1

    样例1地雷的分布只有下图一种:

    样例2地雷的分布只有一种:对应题目描述中的例图

    分析:

    本题从简单情况开始考虑。

    1.一维的情况:

    每个格子内有一个数字,但具体数字不详。但知道该格子和左右两个相邻的格子内的数字之和。

    样例:

      一维格子中的数字之和:4 8 9 8 6 6 5

      一维格子中的数字:      2 2 4 3 1 2 3

    那么,这时正中央格子中的数字最大是多少呢?

     2.按模3的余数分类讨论:

    考虑上面的样例,把第1、第4和第7三个数加起来就可以得到所有格子的数字之和

    把第2和第6二个数加起来就可以得到除正中央格子以外所有格子的数字之和。

    两个结果相减,就可以推出正中央的数字为(4+8+5)-(8+6)=3

    当长度模3余1时我们都可以这样计算得到正中央的数字(因为R一定为奇数,此时一定存在正中央的格子)

    同样,当长度模3余2时,也可以求出两种之和,得到正中央的数字。

    另一方面,当长度模3余0时,无法直接计算除正中央格子以外所有格子的数字之和。但是,可以求出重复计算了正中央的格子两次之和,再通过与全体之和相减得到正中央的数字。

    3.推广到2维

     可以用前面介绍的方法求出每行及其上下两行所含的地雷总数,然后通过相减就能得到正中央那一行地雷的总数了。

    4.本题的陷阱

       本题求最大值,但其实答案是唯一的。

     1 const maxn=60;
     2 var
     3   r,c,n,ans:integer;
     4   a:array[1..maxn,1..maxn] of integer;
     5   rows:array[1..maxn] of integer;
     6   procedure print(x:integer);
     7   begin
     8     writeln(x);
     9   end;
    10   function solve(i:integer):integer;
    11   var j,sum:integer;
    12   begin
    13         sum:=0;
    14         if (c mod 3=1) or(c mod 3=2)  then
    15         begin
    16           j:=1;
    17           while j<= c do begin sum:=sum+a[i,j] ;j:=j+3;end;
    18         end
    19         else
    20         begin
    21           j:=2;
    22           while j<=c do begin sum:=sum+a[i,j];j:=j+3;end;
    23         end;
    24       solve:=sum;
    25 
    26   end;
    27   function sol(j,m:integer):integer;
    28   var sum:integer;
    29   begin
    30     sum:=0;
    31     while j<=m do
    32       begin
    33         sum:=sum+rows[j] ;
    34         j:=j+3;
    35       end;
    36    sol:=sum;
    37   end;
    38   function center:integer;
    39   var sum:integer;
    40   begin
    41     if r mod 3=1 then
    42     sum:=sol(1,r)-sol(2,r div 2-1)-sol(r div 2+3,r)
    43     else if  r mod 3=2 then sum:=sol(2,r)-sol(1,r div 2-1)-sol(r div 2+3,r)
    44     else begin
    45       sum:=sol(1,r div 2 )+sol(r div 2+2,r)-sol(2,r-1);end;
    46     exit(sum);
    47   end;
    48 
    49   procedure main(r,c:integer);
    50   var i :integer;
    51   begin
    52     for i:=1 to r do
    53       begin rows[i]:=solve(i); end;
    54     writeln;
    55     ans:=center;
    56     print(ans);
    57   end;
    58   procedure init;
    59   var k,i,j:integer;
    60   begin
    61     assign(input,'mine.in');reset(input);
    62     readln(n);
    63     for k:=1 to n do
    64       begin
    65         readln(r,c);
    66         for i:=1 to r do
    67           for j:=1 to c do
    68             begin
    69               read(a[i,j]);
    70             end;
    71         main(r,c);
    72       end;
    73       close(input);
    74   end;
    75 begin
    76   init;
    77 end.
    View Code
  • 相关阅读:
    vim的script、function及command
    Vim中如何移动光标
    command模式下命令的匹配及help内容的搜索
    为什么vim编辑模式下ctrl-w可以前向删除单词及按键映射的展开
    gcc如何实现C++中函数auto返回类型推导
    sqlserver 列转行
    【java笔记】可变长参数(...)
    【c#笔记】可变长参数(params)
    【c#笔记】c#与java的差异:接口定义实现
    【java笔记】Calendar类的陷阱
  • 原文地址:https://www.cnblogs.com/ssfzmfy/p/3914992.html
Copyright © 2020-2023  润新知