CF706E.Working routine(十字链表)

题目链接:https://vjudge.net/problem/CodeForces-706E
题意:给出一个n*m的矩阵,q个任务,每个任务要求将两个相同大小的子矩阵块交换位置。输出最后形成的新矩阵
解题思路:
暴力一个个元素交换肯定会超时
可以发现一个子矩阵内部都是相联系的(不会改变的),交换两个矩阵,只需要将两个矩阵的上下左右边界交换一下就可以了。
所以每次交换,更新交换一下两个子矩阵上下左右边界对应即可

#include<iostream>
#include<cstdio>
using namespace std;
#define maxn 1010
struct node{
	int r;
	int d;
	int v;
}ma[maxn*maxn];
int a[maxn][maxn];
int b[maxn][maxn];
int n,m,q;
int x1,x2,y,y2,h,w;
int move(int p,int d,int r){
	while(r--){
		p=ma[p].r;
	}
	while(d--){
		p=ma[p].d;
	}
	return p;
}
int main(){
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&a[i][j]);
		}
	}
	int t=0;
	//从(0,0)开始,这样矩阵的边界永远不会变化
	//为每一个矩阵元素赋予一个编号,方便一维结构体数组的操作
	for(int i=0;i<=n;i++){
		for(int j=0;j<=m;j++){
			b[i][j]=t++;
			ma[b[i][j]].v=a[i][j];
			if(i){
				ma[b[i-1][j]].d=b[i][j];
			}
			if(j){
				ma[b[i][j-1]].r=b[i][j];
			}
		}
	}
	while(q--){
		scanf("%d%d%d%d%d%d",&x1,&y,&x2,&y2,&h,&w);
		//stx对应第一个矩阵的左上角的左上  
		//sty对应第二个矩阵的左上角的左上
		int stx=move(b[0][0],x1-1,y-1);
		int sty=move(b[0][0],x2-1,y2-1);
		//交换矩阵的上边界
		int up1=move(stx,0,1);
		int up2=move(sty,0,1);
		for(int i=1;i<=w;i++){
			swap(ma[up1].d,ma[up2].d);
			up1=ma[up1].r;
			up2=ma[up2].r;
		}
		//交换矩阵的左边界
		int left1=move(stx,1,0);
		int left2=move(sty,1,0);
		for(int i=1;i<=h;i++){
			swap(ma[left1].r,ma[left2].r);
			left1=ma[left1].d;
			left2=ma[left2].d;
		}
		//交换矩阵的下边界
		int down1=move(stx,h,1);
		int down2=move(sty,h,1);
		for(int i=1;i<=w;i++){
			swap(ma[down1].d,ma[down2].d);
			down1=ma[down1].r;
			down2=ma[down2].r;
		}
		//交换矩阵的右边界
		int right1=move(stx,1,w);
		int right2=move(sty,1,w);
		for(int i=1;i<=h;i++){
			swap(ma[right1].r,ma[right2].r);
			right1=ma[right1].d;
			right2=ma[right2].d;
		}
	}
	int st=b[0][0];
	for(int i=1;i<=n;i++){
		st=ma[st].d;
		int stp=st; 
		for(int j=1;j<=m;j++){
			stp=ma[stp].r;
			if(j!=m)
				printf("%d ",ma[stp].v);
			else
				printf("%d\n",ma[stp].v);
		}
	}
	return 0;
}





猜你喜欢

转载自blog.csdn.net/littlegoldgold/article/details/106785537
今日推荐