P7115 [NOIP2020] 移球游戏 思路简记
好题
先手玩一下 (只有颜色 ) 的情况:
我们假设柱子 上有 个 ,那就先把柱子 顶端的 个球移到 ,变成这样:
然后把柱子 的所有 移到柱子 上,所有 移到柱子 3上:
然后再把这些移走的 按顺序移回到柱子 ,并把柱子 剩下的 个数移到柱子 上:
然后把柱子 上的 个 移到柱子 上:
最后再将柱子 所有的 移到柱子 上,所有的 移到柱子 上,那么就移好了:
总操作次数为
考虑能不能把多种颜色的情况转换成很多个两种颜色的问题
可以想到我们设一个值 使 的数全部变为 , 的数全部变为 ,然后将 和 分治求解。
很显然对于每个区间 ,将 设为 时操作次数是最优的。
每次 ,我们将 和 中没有复原的柱子两两匹配,我们令两根柱子分别为 和 ,这样, 和 中如果 的个数大于 的个数,那么将 还原,否则将 还原,然后继续递归下去 和 就行了。
计算一下总操作次数:
那么
计算一下,这是 的
#include<bits/stdc++.h>
using namespace std;
const int N=55;
const int M=405;
#define tp(x) a[x][top[x]]
int n,m,tot;
int a[N][M],top[N];
int ans[820005][2];
inline void move(int x,int y){
ans[++tot][0]=x,ans[tot][1]=y;
a[y][++top[y]]=a[x][top[x]--];
}
inline void solve(int l,int r){
if(l==r) return;
int mid=l+r>>1;
bitset <N> vis;
for(int i=l;i<=mid;++i)
for(int j=mid+1;j<=r;++j){
if(vis[i]||vis[j]) continue;
int cnt=0;
for(int k=1;k<=m;++k)
cnt+=(a[i][k]<=mid)+(a[j][k]<=mid);
if(cnt>=m){
cnt=0;
for(int k=1;k<=m;++k) cnt+=(a[i][k]<=mid);
for(int k=1;k<=cnt;++k) move(j,n+1);
while(top[i]) move(i,tp(i)<=mid?j:n+1);
for(int k=1;k<=cnt;++k) move(j,i);
for(int k=1;k<=m-cnt;++k) move(n+1,i);
for(int k=1;k<=m-cnt;++k) move(j,n+1);
for(int k=1;k<=m-cnt;++k) move(i,j);
while(top[n+1]) move(n+1,(top[i]!=m&&tp(n+1)<=mid)?i:j);
vis[i]=1;
}
else{
cnt=0;
for(int k=1;k<=m;++k) cnt+=(a[j][k]>mid);
for(int k=1;k<=cnt;++k) move(i,n+1);
while(top[j]) move(j,tp(j)>mid?i:n+1);
for(int k=1;k<=cnt;++k) move(i,j);
for(int k=1;k<=m-cnt;++k) move(n+1,j);
for(int k=1;k<=m-cnt;++k) move(i,n+1);
for(int k=1;k<=m-cnt;++k) move(j,i);
while(top[n+1]) move(n+1,(top[j]!=m&&tp(n+1)>mid)?j:i);
vis[j]=1;
}
}
solve(l,mid),solve(mid+1,r);
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j)
cin>>a[i][++top[i]];
solve(1,n);
cout<<tot<<endl;
for(int i=1;i<=tot;++i)
cout<<ans[i][0]<<" "<<ans[i][1]<<endl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现