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