zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    使用tcmalloc编译启动时宕机
    使用tcmalloc编译出现undefined reference to `sem_init'
    使用AddressSanitizer做内存分析(一)——入门篇
    VIM-美化你的标签栏
    Entity Framework Code First (六)存储过程
    Entity Framework Code First (五)Fluent API
    Entity Framework Code First (四)Fluent API
    Entity Framework Code First (三)Data Annotations
    Entity Framework Code First (二)Custom Conventions
    Entity Framework Code First (一)Conventions
  • 原文地址:https://www.cnblogs.com/KnightL/p/14125192.html
Copyright © 2011-2022 走看看