把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【思维·模拟】jzoj1433数码问题 纪中集训提高B组

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


考场上唯一A了的题,但还是想写一写,挺有意思的。
刚开始看错了题面以为询问之间相互独立 (那这不是大水题吗)
认真读了题目发现不是2333。
整个数组完全模拟肯定是不可能的,而且 n n n那么大。
发现 k k k比较小,于是将询问离线,只存需要被询问的点的位置更新状况,每一次操作都看一下后面的点再经过操作之后跑到哪里去了,更新它的位置,复杂度 k 2 k^2 k2,但其实还跑不满。

后面又在想如果没有规定先移行还是先移列的问题,那么移行移列的顺序是会影响答案的,那如果把这道题改成不限制先移什么,然后求最小的移动次数呢?
唔,好像有点难。(反正本蒟蒻没有思考出来)

#pragma GCC optimize(2)
//shu_ma_wen_ti 
/*
每进行一次旋转行操作->列++
每进行一次旋转列操作->行++
先移列再移行
最少? 
*/
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXK 1005
#define LL long long
int n,k;
struct node{
	int x,y,r,c;
}nd[MAXK];
inline int rd()
{
	int f=1,x=0;char c=getchar();
	while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
	while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return f*x;
}
int main()
{
	n=rd(),k=rd();
	for(register int i=1;i<=k;i++)
	{
		int num=rd();nd[i].r=rd(),nd[i].c=rd();
		nd[i].x=num/n,nd[i].y=num%n;
		if(nd[i].y) nd[i].x++;
		if(nd[i].y==0) nd[i].y=n;
	}
	for(register int i=1;i<=k;i++)
	{
		int move1=0,move2=0,ans=0;
		if(nd[i].c>=nd[i].y) move2=nd[i].c-nd[i].y,ans+=move2;
		else if(nd[i].c<nd[i].y) move2=n-nd[i].y+nd[i].c,ans+=move2;
		if(nd[i].r>=nd[i].x) move1=nd[i].r-nd[i].x,ans+=move1;
		else if(nd[i].r<nd[i].x) move1=n-nd[i].x+nd[i].r,ans+=move1;
		printf("%d\n",ans);
		for(register int j=i+1;j<=k;j++)
		{
			if(nd[j].x==nd[i].x)nd[j].y=(nd[j].y+move2+n-1)%n+1;
			if(nd[j].y==nd[i].c)nd[j].x=(nd[j].x+move1+n-1)%n+1;
			//printf("*%d %d %d\n",j,nd[j].x,nd[j].y);
		}
	}
	return 0;
}
posted @ 2019-08-06 20:03  Starlight_Glimmer  阅读(10)  评论(0编辑  收藏  举报  来源
浏览器标题切换
浏览器标题切换end