题解1433. 数码问题 (Standard IO)

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行,每行输出一个整数,表示操作次数。
 

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

  这一题我们先看数据范围,N<=10000 ,我们可以知道,是不可以拿一个二维数组去记录每一个点的,而且时间复杂度也不可以依赖于N,所以我们只能从K下手,对于每一次询问,其实答案非常好算,但是比较难的是每次算出答案后,进行的操作对其他数初始位置的影响,我们可以设置两个结构体数组x[i]和y[i],分别有move,now两个元素。表示第i次询问,在x和y轴方向分别移动了多少,x[i].now表示这一次操作,x移动的是哪一行(因为移动的是一行,所以要用y来表示是哪一行,因为只有y相同,x不相同),move说明向右移了多少,y[i].now表示这次操作移动的是哪一列(同样,一列上的数,x相同,y不相同,所以用x表示),move表示移动了多少,因为题目上规定了先向右移,再向下移,所以我们先计算这一次操作的行,在计算列。

  我们在每一次新的操作时,将以前操作时保存下来的哪一行哪一列移动了多少,一个一个遍历以求出这个数现在真实的位置,在进行计算。

  对于计算时非常简单的,分两种情况,1-将要达到的坐标比现在的坐标大(x坐标,y坐标同时适用),那么直接相减得到的差就是要进行多少次操作,知道xy都达到要求,就可以输出答案。2-即将要达到的坐标比现在的坐标小,我们的操作只能向下向后走,无法回头,只能到达边界后回到第一格,转化成问题1。

Code:

#include<iostream>
#include<cstdio>
using namespace std;
struct number{
    long long move;
    long long now;
}x[1010],y[1010];
long long n,k,x2,y2;
long long num[1010],x1[1010],y1[1010],ans;
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>k;
    for(int i=1;i<=k;i++) cin>>num[i]>>y1[i]>>x1[i];
    for(int i=1;i<=k;i++){
        ans=0;
        x2=num[i]%n;
        if(num[i]%n==0) x2=n;
        y2=num[i]/n;
        if(num[i]%n!=0) y2++;
        for(int j=1;j<i;j++){            
            if(x[j].now==y2){ 
                x2=(x[j].move+x2)%n;
                if(x2==0) x2=n;
            }
            if(y[j].now==x2){
                y2=(y[j].move+y2)%n;
                if(y2==0) y2=n;
            }
        }
        if(x1[i]<x2){
            ans+=n-x2+x1[i];
            x[i].move=n-x2+x1[i];
            x[i].now=y2;
        }
        else if(x1[i]>x2){
            ans+=x1[i]-x2;
            x[i].move=x1[i]-x2;
            x[i].now=y2;
        }        
        if(y1[i]<y2){
            ans+=n-y2+y1[i];
            y[i].move=n-y2+y1[i];
            y[i].now=(x2+x[i].move)%n;
            if(y[i].now==0) y[i].now=n;
        }
        else if(y1[i]>y2){
            ans+=y1[i]-y2;
            y[i].move=y1[i]-y2;
            y[i].now=(x2+x[i].move)%n;
            if(y[i].now==0) y[i].now=n;
        }
        cout<<ans<<endl;
    }
}

  

谢谢阅读。

猜你喜欢

转载自www.cnblogs.com/tianbowen/p/11305317.html