数码问题 纪中 1433 优美的暴力
Description
Alice有一个N*N的格子,把1-N^2按照从上到下从左到右的顺序填进表格中,允许在表格上进行两种操作:
(1) 旋转行——这一行的数向右移动一个位置,而最后一列的数会移到第一列;
(2) 旋转列——这一列的数向下移动一个位置,最后一行的数会移到第一行。
Alice想把数X移到(R,C)处可以采用以下方法:
•如果X不在C这一列,通过旋转行操作把X移到C这一列;
•如果X不在R这一行,通过旋转列操作把X移到R这一行。
下面是一个把6移到(3,4)的例子:
Alice现在想采用上述方法,依次把K个数移到各自的目标位置,编程计算每个数需要几次操作。
Input
第一行包含两个整数N(12<=N<=10000)和K(1<=K<=1000)。
接下来K行,每行包含三个整数X(1<=X<=N^2)、R和C(1<=R,C<=N),描述需要移动的数以及目标位置。
Alice必须按照输入顺序依次移动。
Output
输出K行,每行输出一个整数,表示操作次数。
分析
因为n的范围很大,所以我们要考虑k。
我们用数组a[2*k],a[2*k-1]表示第k次操作改变的行、列和移动的值。
然后,后面的移动要求就向前枚举以前的改变操作,和自己有关的就改变自己的坐标。
具体见程序
代码
var
a:array[1..1010,1..3] of longint;
n,m:longint;
w,x,y:longint;
x1,y1:longint;
i,j,k:longint;
ans:longint;
nm:longint;
begin
readln(n,m);
nm:=0;
for i:=1 to m do
begin
readln(w,x,y);
x1:=(w div n)+1;
y1:=w mod n;
if y1=0 then
begin
x1:=x1-1;
y1:=n;
end;
for j:=1 to nm do
begin
if x1=a[j,1]
then begin
y1:=y1+a[j,3];
if y1>n then y1:=y1-n;
end;
if y1=a[j,2]
then begin
x1:=x1+a[j,3];
if x1>n then x1:=x1-n;
end;
end;
ans:=0;
if y1>y
then
begin
ans:=y+(n-y1);
y1:=y;
nm:=nm+1;
a[nm,1]:=x1;
a[nm,3]:=ans;
end
else
begin
ans:=y-y1;
y1:=y;
nm:=nm+1;
a[nm,1]:=x1;
a[nm,3]:=ans;
end;
if x1>x
then
begin
k:=x+(n-x1);
x1:=x;
ans:=ans+k;
nm:=nm+1;
a[nm,2]:=y1;
a[nm,3]:=k;
end
else
begin
k:=x-x1;
x1:=x;
ans:=ans+k;
nm:=nm+1;
a[nm,2]:=y1;
a[nm,3]:=k;
end;
writeln(ans);
end;
end.