题目链接: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;
}