分析:
很有趣(du)的一道题目啊。。。
构造法很简单,首先,对原序列按x坐标排序,设第i个位置排序后的序号为idiidi然后把每个位置(xi,yi)(xi,yi)平移到(idi,yi)(idi,yi)。这样只需要在yiyi这条线上平移,很容易发现这是不可能矛盾的。
现在我们让每个格子都有一个不同的横坐标xixi,说明每一列上最多只有一个格子。这时就可以直接把(idi,yi)(idi,yi)的格子移动到(idi,i)(idi,i)去,全部做完后,再把所有(idi,i)(idi,i)移动到(i,i)(i,i)去。
后面两步都因为某一坐标唯一,所以绝对合法(不会撞在一起)。
然后对目标状态再做一次,输出答案把这部分反向就可以了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 10810
#define y1 chenchunhua
using namespace std;
typedef long long ll;
int n,m;
struct node{
int x,y;
int id;
bool operator <(const node&a) const {
if(x==a.x)
return y<a.y;
return x<a.x;
}
}p[MAXN];
pair<int,int> ansf[MAXN],anst[MAXN];
int move(int top,int x0,int y0,int x1,int y1){
while(x0!=x1){
int xx0=x0;
if(x1<x0)
x0--;
else
x0++;
ansf[++top]=make_pair(xx0,y0);anst[top]=make_pair(x0,y0);
}
while(y0!=y1){
int yy0=y0;
if(y1<y0)
y0--;
else
y0++;
ansf[++top]=make_pair(x0,yy0);anst[top]=make_pair(x0,y0);
}
return top;
}
int solve(int top){
sort(p+1,p+1+m);
for(int i=1;i<=m;i++){
if(i<p[i].x){
top=move(top,p[i].x,p[i].y,i,p[i].y);
p[i].x=i;
}
}
for(int i=m;i>=1;i--){
top=move(top,p[i].x,p[i].y,i,p[i].y);
p[i].x=i;
}
for(int i=1;i<=m;i++){
top=move(top,p[i].x,p[i].y,p[i].x,p[i].id);
p[i].y=p[i].id;
}
for(int i=1;i<=m;i++){
top=move(top,p[i].x,p[i].y,p[i].id,p[i].y);
p[i].x=p[i].id;
}
return top;
}
int main(){
SF("%d%d",&n,&m);
for(int i=1;i<=m;i++){
SF("%d%d",&p[i].x,&p[i].y);
p[i].id=i;
}
int cnt=solve(0);
for(int i=1;i<=m;i++){
SF("%d%d",&p[i].x,&p[i].y);
p[i].id=i;
}
int cnt1=solve(cnt);
PF("%d\n",cnt1);
for(int i=1;i<=cnt;i++)
PF("%d %d %d %d\n",ansf[i].first,ansf[i].second,anst[i].first,anst[i].second);
for(int i=cnt1;i>cnt;i--)
PF("%d %d %d %d\n",anst[i].first,anst[i].second,ansf[i].first,ansf[i].second);
}