• NOIP2020 移球游戏


    Description

    给定 (n+1) 个栈,前 (n) 个栈内有不定的 (m) 个元素,最后一个栈为空,每个栈的最大容量为 (m)
    每种颜色都有 (m) 种,求任意一种方法,使得在 (820000) 次操作内把相同的元素都移动到同一个栈内

    Solution

    考虑移动单个元素
    枚举元素种类,设当前枚举到的元素种类为 (Now)

    移动规则如下

    • 统计第一个柱子上元素 (Now) 的数量 (Count)

    • 从第 (Now) 个栈移动 (Count) 个元素到第 (Now+1) 个栈上(为了预留出位置存放元素 (Now)

    • 把第一根柱子的元素分离,是 (Now) 的放到栈 (Now) 内,不是的放到栈 (Now+1)

    • 从栈 (Now+1) 移动 (m-Count) 个元素到第一个柱子(为第二个柱子让位)

    • 把第二个栈内不是 (Now) 的元素移动到第一个栈上,放不开了就放到第 (Now+1) 个栈内

    • ( ext{swap}) 分别交换第一和第 (Now),第二和第 (Now+1) 个栈(这样不停操作第一二个栈和枚举的栈 (Now) 就可以了)

    • 然后 (k) 枚举第一到第 (Now) 个栈,分别统计他们里面元素 (Now) 的数量,然后把第 (Now) 个栈移走相同数量的元素到 (Now+1) 上(原因同第二步)

    • 分离当前枚举到的栈内的元素,把元素 (Now) 都放到栈 (Now) 内,其他的都放到栈 (Now+1)

    • ( ext{swap}) 分别交换第 (k) 和第 (Now),第 (k) 和第 (Now+1) 个栈(证明栈 (Now) 已被处理完,之后不会再对其操作)

    • 然后把第一到第 (Now) 个栈上方的 (Now) 元素都移到栈 (Now+1) 上,放上栈 (Now) 内的元素 (Now)(此时栈 (Now) 上方全是元素 (Now)

    如此,可以处理完所有的颜色
    然而,这个方法并不适用于 (n=2) 的情况
    原因是当枚举第一个颜色时,第 (Now+1) 个栈就是第二个栈
    所以要特判处理
    移动规则与 (ngeq3) 时大同小异
    无非是

    • 统计第一栈内元素 (1) 的个数,然后从第二栈移动相同的数量到第三栈

    • 分离第一栈,把元素 (1) 放到第二栈上,其他的放到第三栈上

    • 然后把第二栈上的元素 (1) 移回第一栈,使第一栈此时只有元素 (1)

    • 从第三栈移动 (m-Count) 个元素到第一栈,剩下的移回第二栈

    • 把那 (m-Count) 个元素移回去

    • 分离第二栈,是 (1) 的放回第一栈,不是的放回第三栈

    因为一种只有两种元素,且可以确定第一栈全为 (1) ,第三栈全为 (2)
    所以至此问题得到解决

    极限操作次数为 (sum_{i=1}^n im + 5m),大概需要 (600000) 次,时间复杂度同操作次数

    Code

    #include<bits/stdc++.h>
    #define rr register 
    #define maxn 410
    #define maxm 850010 
    
    using namespace std;
    
    int n,m,cnt[maxn],fr[maxm],to[maxm];
    int Col[maxn][maxn],P[maxn];
    int Ans; 
    //Col[i][j]第 i 根柱子上的第 j 个球的颜色 
    //P[i]第 i 跟柱子
    //cnt[i]当前柱子上球的数量  
    
    inline int Read(){
    	int s=0,w=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
    	return s*w;
    }
    
    inline int Get_Count(int x,int y){
    	int ans=0;
    	for(int i=1;i<=m;i++) if(Col[x][i]==y) ans++;
    	return ans;
    }
    
    inline void Move_Ball(int x,int y){
    	fr[++Ans]=x;to[Ans]=y;
    	Col[y][++cnt[y]]=Col[x][cnt[x]--];
    }
    
    inline int Top(int x){return Col[x][cnt[x]];}
    
    int main(){
    	n=Read();m=Read();
    	for(rr int i=1;i<=n;i++){cnt[i]=m;for(rr int j=1;j<=m;j++) Col[i][j]=Read();}
    	for(rr int i=1;i<=n+1;i++) P[i]=i;cnt[n+1]=0;  
    	for(rr int Now=n;Now>=3;Now--){
    		int Count=Get_Count(P[1],Now);
    		for(rr int i=1;i<=Count;i++) Move_Ball(P[Now],P[Now+1]); 
    		for(rr int i=1;i<=m;i++) if(Top(P[1])==Now) Move_Ball(P[1],P[Now]);else Move_Ball(P[1],P[Now+1]);
    		for(rr int i=1;i<=m-Count;i++) Move_Ball(P[Now+1],P[1]);
    		for(rr int i=1;i<=m;i++) if(Top(P[2])==Now||cnt[P[1]]==m) Move_Ball(P[2],P[Now+1]);else Move_Ball(P[2],P[1]);
    		swap(P[1],P[Now]);swap(P[2],P[Now+1]);
    		for(rr int k=1;k<Now;k++){
    			Count=Get_Count(P[k],Now);
    			for(rr int i=1;i<=Count;i++) Move_Ball(P[Now],P[Now+1]); 
    		    for(rr int i=1;i<=m;i++) if(Top(P[k])==Now) Move_Ball(P[k],P[Now]);else Move_Ball(P[k],P[Now+1]); 
    		    swap(P[k],P[Now+1]);swap(P[k],P[Now]);
    		}
    		for(rr int i=1;i<Now;i++) while(Top(P[i])==Now) Move_Ball(P[i],P[Now+1]);
    		for(rr int i=1;i<Now;i++) while(cnt[P[i]]<m) Move_Ball(P[Now],P[i]);  
    	}
    	int Count=Get_Count(P[1],1); 
    	for (rr int i=1;i<=Count;i++) Move_Ball(P[2],P[3]);
    	for (rr int i=1;i<=m;i++) if (Top(P[1])==1) Move_Ball(P[1],P[2]);else Move_Ball(P[1],P[3]);
    	for (rr int i=1;i<=Count;i++) Move_Ball(P[2],P[1]);
    	for (rr int i=1;i<=m-Count;i++) Move_Ball(P[3],P[1]);
    	while (cnt[P[3]]) Move_Ball(P[3],P[2]);
    	for (rr int i=1;i<=m-Count;i++) Move_Ball(P[1],P[3]);
    	for (rr int i=1;i<=m;i++) if (Top(P[2])==1) Move_Ball(P[2],P[1]);else Move_Ball(P[2],P[3]);
    	printf("%d
    ",Ans);for(int i=1;i<=Ans;i++) printf("%d %d
    ",fr[i],to[i]); 
    	return 0;
    }
  • 相关阅读:
    Oracle 单引号与双引号的区别
    oracle 生成随机数
    oracle 表空间及查看所有用户的表空间
    字节和字符的区别
    java io
    Oracle 基础
    gvim 常用键
    Python之struct
    Python之MySQLdb
    Python之sqlite3
  • 原文地址:https://www.cnblogs.com/KnightL/p/14125192.html
Copyright © 2020-2023  润新知