题目链接:https://www.luogu.com.cn/problem/P7115
n+1个柱子,前面n个上面各有m个球,球有n种颜色,每种m个。
你每次可以把一个柱子最上面的球放到另一个上面,要求在820000次内使得同种颜色的球都在同一个柱子上。
输出方案
2≤n≤50,2≤m≤400
这题好难啊,用的是洛谷题解上的做法。
首先我们枚举一种颜色x,将这种颜色标记为1其他都为0。
然后开始的状态是这样的

然后考虑先构造一个全部都是0的竖列
我们先记录第一柱的1的个数tmp,然后把第n−1柱子的tmp个丢进第n+1柱,然后把第一柱分离到后面两个柱子(1的放到n,0的放到n+1)

然后把原来的0放到第一柱,然后分离第二柱,如果是0放到第一柱否则放到第n+1柱(如果第一柱已经满了就放进n+1柱)

然后交换一下柱子序号(用个数组存一下就好了)就变成了

然后再考虑构造全1柱
我们把同理把第1柱分裂到第n和第n+1柱就变成了

此时第n+1柱子上面全部是1而第n柱上面都是0,然后此时我们再把剩下n个柱子依次分离就能把所有的1提到最上面,然后把所有的1集合就好了。
最后弄出n−1个全0柱和一个全1柱我们就可以把全一柱去掉然后缩小n的值。
一直重复到n=2时我们发现我们的方法不再适用,需要特别处理。
我们按照前面的方法把第一柱分离到2和3

然后把0和1丢到第一个柱子,然后再把1丢进第3个柱子

然后分离第二个柱子就好了
然后这样就能过了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=410;
int n,m,a[N][N],cnt[N],p[N];
vector<int> aL,aR;
void mov(int x,int y){
aL.push_back(x);
aR.push_back(y);
a[y][++cnt[y]]=a[x][cnt[x]--];
return;
}
int count(int x,int y){
int ans=0;
for(int i=1;i<=m;i++)
ans+=(a[x][i]==y);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
cnt[i]=m;p[i]=i;
}
p[n+1]=n+1;
for(int k=n;k>=3;k--){
int tmp=count(p[1],k);
for(int i=1;i<=tmp;i++)mov(p[k],p[k+1]);
for(int i=1;i<=m;i++)
if(a[p[1]][cnt[p[1]]]==k)mov(p[1],p[k]);
else mov(p[1],p[k+1]);
for(int i=1;i<=m-tmp;i++)mov(p[k+1],p[1]);
for(int i=1;i<=m;i++)
if(a[p[2]][cnt[p[2]]]==k)mov(p[2],p[k+1]);
else if(cnt[p[1]]<m)mov(p[2],p[1]);
else mov(p[2],p[k+1]);
swap(p[1],p[k]);swap(p[2],p[k+1]);
for(int i=1;i<k;i++){
int tmp=count(p[i],k);
for(int j=1;j<=tmp;j++)mov(p[k],p[k+1]);
for(int j=1;j<=m;j++)
if(a[p[i]][cnt[p[i]]]==k)mov(p[i],p[k]);
else mov(p[i],p[k+1]);
swap(p[i],p[k+1]);swap(p[k],p[i]);
}
for(int i=1;i<k;i++){
while(a[p[i]][cnt[p[i]]]==k)mov(p[i],p[k+1]);
while(cnt[p[i]]<m)mov(p[k],p[i]);
}
}
int tmp=count(p[1],1);
for(int i=1;i<=tmp;i++)mov(p[2],p[3]);
for(int i=1;i<=m;i++)
if(a[1][cnt[p[1]]]==1)mov(p[1],p[2]);
else mov(p[1],p[3]);
for(int i=1;i<=m-tmp;i++)mov(p[3],p[1]);
for(int i=1;i<=tmp;i++)mov(p[2],p[1]);
while(cnt[p[3]])mov(p[3],p[2]);
for(int i=1;i<=tmp;i++)mov(p[1],p[3]);
for(int i=1;i<=m;i++)
if(a[2][cnt[p[2]]]==1)mov(p[2],p[3]);
else mov(p[2],p[1]);
printf("%d\n",aL.size());
for(int i=0;i<aL.size();i++)
printf("%d %d\n",aL[i],aR[i]);
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构