前言
自己的方法应该没错来着...时间不够,考试时没调出来
题目
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行,每行输出一个整数,表示操作次数。
Sample Input
输入1: 4 1 6 3 4 输入2: 4 2 6 3 4 6 2 2 输入3: 5 3 1 2 2 2 2 2 12 5 5
Sample Output
输出1: 3 输出2: 3 5 输出3: 2 5 3
分析
思路:每次移动数字时,实际是行和列的移动,把同在需要移动的行、列上的被询问的数也跟着移动即可
考试时奇奇怪怪的做法
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1e4;
int r[MAXN+5],c[MAXN+5];//行、列的移动情况
int n,k,a,dx,dy,x,y;
int ans1,ans2;
void Solve()
{
//先求原始坐标
int t=a,rest=a;
t/=n,rest%=n;
if(rest!=0)
t++;
else
rest=n;
x=t,y=rest;
//printf("*%d:%d %d\n",a,x,y);
//printf("change:%d %d\n",c[y],r[x]);
int tx=x,ty=y;
x+=c[ty],y+=r[tx];
//printf("^%d:%d %d\n",a,x,y);
x=(x+n)%n,y=(y+n)%n;
if(!x) x=n;
if(!y) y=n;
//printf("*%d:%d %d\n",a,x,y);
if(x<=dx)
ans1=dx-x,c[y]-=x-dx;
else
ans1=n-x+dx,c[y]-=x-dx;
if(y<=dy)
ans2=dy-y,r[x]+=dy-y;
else
ans2=n-y+dy,r[x]-=y-dy;
}
int main()
{
scanf("%d%d",&n,&k);
while(k--)
{
scanf("%d%d%d",&a,&dx,&dy);
Solve();
printf("%d\n",ans1+ans2);
}
return 0;
}
/*
感觉重点是确定数a的位置...
要点:特判一下尾数的情况
*/
AC代码
注意:
1.第一次行的移动后,数x已经移动到了dy列上,所以代值也要代dy
2.超过n要取余
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1e4;
int dx[MAXN+5],dy[MAXN+5];
int n,k;
struct node
{
int num,x,y;
}a[MAXN+5];
void move1(int id,int y,int d)//y列上下移动
{
for(int i=id+1;i<=k;i++)
{
if(a[i].y==y)
{
a[i].x+=d;
a[i].x%=n;
if(a[i].x==0)
a[i].x=n;
}
}
}
void move2(int id,int x,int d)//x行左右移动
{
for(int i=id+1;i<=k;i++)
{
if(a[i].x==x)
{
a[i].y+=d;
a[i].y%=n;
if(a[i].y==0)
a[i].y=n;
}
}
}
void Cal(int i,int num)
{
int t=num,rest=num;
t/=n,rest%=n;
if(rest!=0)
t++;
else
rest=n;
a[i].x=t,a[i].y=rest;
}
int Solve(int id,int dx,int dy)
{
int ans1=0,ans2=0;
int x=a[id].x,y=a[id].y;
//该数左右移动,实际是x行左右移动
if(y<=dy)
ans2=dy-y,move2(id,x,dy-y);
else
ans2=n-y+dy,move2(id,x,n-y+dy);
//该数上下移动,实际是y列上下移动
if(x<=dx)
ans1=dx-x,move1(id,dy,dx-x);
else
ans1=n-x+dx,move1(id,dy,n-x+dx);
return ans1+ans2;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)
{
scanf("%d%d%d",&a[i].num,&dx[i],&dy[i]);
Cal(i,a[i].num);//计算初始位置
}
for(int i=1;i<=k;i++)
printf("%d\n",Solve(i,dx[i],dy[i]));
return 0;
}