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;
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Buyi.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值