当前位置: 代码迷 >> 综合 >> 【构造】Codeforces 1025E Colored Cubes
  详细解决方案

【构造】Codeforces 1025E Colored Cubes

热度:81   发布时间:2023-09-27 06:31:58.0

分析:

很有趣(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--;elsex0++;ansf[++top]=make_pair(xx0,y0);anst[top]=make_pair(x0,y0);}while(y0!=y1){int yy0=y0;if(y1<y0)y0--;elsey0++;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);}