其他分享
首页 > 其他分享> > 【洛谷6892】[ICPC2014 WF] Baggage(构造)

【洛谷6892】[ICPC2014 WF] Baggage(构造)

作者:互联网

点此看题面

构造题

首先,样例给了我们很明显的提示:最少的移动步数就是\(n\)。

所以说,关键在于如何构造。

我们发现一开始肯定可以进行若干次操作,每次先将最右边的一个"AB"移到左边,再将最左边的一个"BA"移到右边。

这样不断搞下去最终中间会出现一段无法如此操作的部分。

然后又发现需要根据\(n\)模\(4\)的余数分成\(4\)类情况讨论,其中\(n\%4=0/1\)的情况样例中有了,而且本身也非常简单。

而\(n\%4=2/3\)的情况关键在于手玩出\(n=6\)和\(n=7\)的情况。

注意,\(n\%4=3\)的时候并不是在\(n=3\)的情况基础上推得的(当然由于可能存在\(n=3\),这一部分的手玩也是不可避免的),而是由\(n=7\)推得的!所以不要像我那样试着用\(n=3\)来推\(n=7\)直接懵了\(1\)个小时。。。

处理完中间部分后,不同情况的操作又变得统一了起来,每次先将左边最靠右的一个"BB"移到右边,再将右边最靠左的一个"AA"移到左边。

具体实现详见代码吧,因为具体的构造过程也很难讲清楚。

代码:\(O(n)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define Move(x) (printf("%d to %d\n",x,z),z=x)//将x移到空位上
using namespace std;
int n; 
int main()
{
	RI i,x,y,z=-1;if(scanf("%d",&n),n==3) return Move(2),Move(5),puts("3 to -3"),0;//特判n=3,由于要用到-3位置,所以无法推广
	for(i=1,x=2*n-2,y=3;i<=n/4-(n%4>=2);++i) Move(x),x-=4,Move(y),y+=4;//通用的开始
	switch(n%4)//按余数分类讨论
	{
		case 0:y=x-2,x+=5;break;case 1:Move(x+2),y=x-4,x+=5;break;
		case 2:Move(x),Move(x-3),Move(x-8),Move(x-4),y=x-10,++x;break; 
		case 3:Move(x-4),Move(x-7),Move(x),Move(x-9),Move(x-3),y=x-12,++x;break;
	}
	for(i=1;i<=n/4;++i) Move(y),y-=4,Move(x),x+=4;return 0;//通用的结束
}

标签:case,WF,ICPC2014,洛谷,int,Move,break,++,define
来源: https://www.cnblogs.com/chenxiaoran666/p/CF6892.html