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


    点此看题面

    • 一张无限长的格子纸条,其中(1sim 2n)位奇数位填着"B",偶数位填着"A",剩余位没有字母。
    • 一次移动操作可以将连续两个有字母的格子中的字母剪切到连续两个没有字母的格子中。
    • 要求构造一组移动步数最少方案,使得所有"A","B"相连且所有"A"在所有"B"前面。
    • (3le nle100)

    构造题

    首先,样例给了我们很明显的提示:最少的移动步数就是(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
    ",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;//通用的结束
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    Sql2000存储过程分页
    扇贝网页记单词插件
    notepad++正则替换保留原内容
    给 QuickTime 播放器添加快进x秒,快退x秒
    谷歌浏览器隐私设置错误 NET::ERR_CERT_AUTHORITY_INVALID 攻击者可能会试图从 xx 窃取您的信息(例如:密码、通讯内容或信用卡信息)。
    Java实体映射工具MapStruct 与BeanUtils性能比较
    阿里DDD项目最佳实践-COLA 架构总览
    Java实体映射工具MapStruct详解
    Martin Fowler大神
    领域模型的核心本质是什么?
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu6892.html
Copyright © 2020-2023  润新知