【杂题】[CodeForces 1172D] Nauuo and Portals【构造】

Description

有一个n*n的网格,你需要在上面设置一些传送门,传送门由两个配对的格子组成,从一个进入会立刻从另一个同一方向出来。

现在有n个人从第1列出发向右走,位于(i,1)的人要走到(ri,n)
n个人从第一行出发向下走,位于(1,i)的人要走到(n,ci)
求一种设置传送门的方案。

n<=1000

Solution

很有意思的一个构造。

我们先考虑第一行第一列
如果他们都是一条直线走过去,那就直接转化成了一个n-1的子问题。

否则我们记位于(p,1)的人要去(1,n),位于(1,q)的人要去(n,1)
我们可以直接在(p,1)和(1,q)放一个传送门,相应的修改第一行的人和第一列的人所在位置,那么一样转化成了一个n-1的子问题。

这样就可以用不超过n个传送门解决了,时间复杂度O(n)

题解说开1000是因为checker是n^2的...

Code

#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 1005
using namespace std;
int r[N],r1[N],c[N],c1[N],n,ans[N][4];
int main()
{
	cin>>n;
	fo(i,1,n) scanf("%d",&r[i]),r1[r[i]]=i;
	fo(i,1,n) scanf("%d",&c[i]),c1[c[i]]=i;
	int cnt=0;
	fo(i,1,n)
	{
		int p=r1[i],q=c1[i];
		if(p==i&&q==i) continue;
		cnt++;
		ans[cnt][0]=p,ans[cnt][1]=i,ans[cnt][2]=i,ans[cnt][3]=q;
		swap(r1[r[i]],r1[r[p]]);
		swap(c1[c[i]],c1[c[q]]);
		swap(r[i],r[p]);
		swap(c[i],c[q]);
	}
	printf("%d\n",cnt);
	fo(i,1,cnt) printf("%d %d %d %d\n",ans[i][0],ans[i][1],ans[i][2],ans[i][3]);
}
posted @ 2019-06-13 22:37  BAJim_H  阅读(262)  评论(0编辑  收藏  举报