当前位置: 首页 > news >正文

题解:CF961C Chessboard

洛谷。

题目传送门。

某次校内模拟赛的 T1。

分析

注意到 \(n\le100\),显然这是一道搜索题。考虑怎么来搜。

我们发现,四块小棋盘可以在左上、右上、左下、右下任意排列,那么构成大棋盘的总方案数就是 \(4!=24\) 种。这个数并不大,我们可以写四重循环来枚举它。对于枚举出来的每一种方案,我们都求出它的代价,然后取最优的。

接下来考虑我们得到一个构造好的大棋盘后,应该怎么求它的代价。容易想到从左上角开始广搜。维护一个队列,队列中的每个结点都有横纵坐标两个属性。每次判断当前结点的右(下)方是否还有不在队列中的结点;如果有,就将这个结点入队。同时,判断当前结点是否与左(上)方的结点同色;如果是,代价加一并将这个结点重新染色。

为确保分讨全面,我们要在广搜过一次后将左上角的颜色改变一次,再重新广搜,两次的结果取最小代价。

然后就做完了。有一点小细节,直接看代码吧。

代码

#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#define inline __inline
#include<iostream>
#include<queue>
using namespace std;const int N=1e2+5;int n;bool a[5][N][N],mat[N<<1][N<<1],vis[N<<1][N<<1];namespace OIfast{char buf[1<<21],*p1,*p2,*top,buffer[1<<21];#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?0:*p1++)#define gc getchar()inline int read(){int n=0;char c=gc;while(!isdigit(c))c=gc;while(isdigit(c))n=(n<<3)+(n<<1)+(c^48),c=gc;return n;}inline bool get_(){char c=gc;while(!isdigit(c))c=gc;return c^48;}}using namespace OIfast;inline void input(){//输入有点长,单开一个函数。n=read();for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)a[1][i][j]=get_();for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)a[2][i][j]=get_();for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)a[3][i][j]=get_();for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)a[4][i][j]=get_();return ;
}inline void gz(int zs/*左上*/,int ys/*右上*/,int zx/*左下*/,int yx/*右下*/){//构造当前枚举到的大棋盘。for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)mat[i][j]=a[zs][i][j];for(int i=1;i<=n;++i)for(int j=n+1,k=1;j<=(n<<1);++j,++k)mat[i][j]=a[ys][i][k];for(int i=n+1,k=1;i<=(n<<1);++i,++k)for(int j=1;j<=n;++j)mat[i][j]=a[zx][k][j];for(int i=n+1,k=1;i<=(n<<1);++i,++k)for(int j=n+1,l=1;j<=(n<<1);++j,++l)mat[i][j]=a[yx][k][l];return ;
}#define pii pair<int,int>
#define x first
#define y secondinline int calc(){//对于已经构造好的大棋盘,求它的代价。for(int i=1;i<=(n<<1);++i)for(int j=1;j<=(n<<1);++j)vis[i][j]=0;int res=0;queue<pii >q;q.push(make_pair(1,1)),vis[1][1]=1;while(!q.empty()){pii cur=q.front();q.pop();int i=cur.x,j=cur.y;vis[i][j]=0;if(i>1)if(mat[i][j]==mat[i-1][j])++res,mat[i][j]^=1;if(j>1)if(mat[i][j]==mat[i][j-1])++res,mat[i][j]^=1;if(i<(n<<1)&&(!vis[i+1][j]))q.push(make_pair(i+1,j)),vis[i+1][j]=1;if(j<(n<<1)&&(!vis[i][j+1]))q.push(make_pair(i,j+1)),vis[i][j+1]=1;
//		if(i<(n<<1)&&j+1<=(n<<1))q.push(make_pair(i+1,j+1));//走不到右下,这一行不能要。}return res;
}inline void getmn(int &a,int b){return a=(a<b?a:b),void();
}inline int solve(){int res=1e9;for(int i=1;i<=4;++i){//枚举左上、右上、左下、右下各放哪一块for(int j=1;j<=4;++j){if(i==j)continue ;for(int k=1;k<=4;++k){if(k==j||k==i)continue ;for(int l=1;l<=4;++l){if(l==k||l==j||l==i)continue ;gz(i,j,k,l)/*左上角不动的情况*/;getmn(res,calc());gz(i,j,k,l),mat[1][1]^=1/*左上角要动的情况*/;getmn(res,calc()+1/*注意,这个地方一定要加上 1,因为改变左上角的颜色本身也会产生贡献*/);}}}}return res;
}signed main(){input();return cout<<solve()<<"\n",0;
}
http://www.jsqmd.com/news/38785/

相关文章:

  • 7年java开发的一些感悟
  • 11.12 NOIP模拟6/多校1 改题记录
  • 文字识别系统代码
  • B4093 [CSP-X2021 山东] 发送快递
  • 从零上手 Rokid JSAR:打造专属 AR 桌面交互式 3D魔方,开启空间创建之旅
  • 微软2025年11月补丁星期二修复1个零日漏洞和63个安全漏洞
  • CF468C Hack it!
  • 深入解析:FT62FC3X 8位MCU单片机选型表,详细解析FT62FC31A/32A/33A/35A/3FA
  • 语法记录
  • Can Large Language Models Detect Rumors on Social Media?
  • 压迫
  • P13573 [CCPC 2024 重庆站] Pico Park
  • 手工安装gcc-13.3.0
  • 深入解析:Cookie、Session、JWT、SSO,网站与 APP 登录持久化与缓存
  • gowin ide linux安装教程
  • AT_arc111_f [ARC111F] Do you like query problems?
  • Win7 隐藏文件夹盘符
  • pythontip 按条件过滤字典
  • DotNetGuide 突破了 9.5K + Star,一份全面的C#/.NET/.NET Core学习、工作、面试指南知识库!
  • 如何把华为mate 60手机备份到移动硬盘
  • Vue实例学习
  • 2.2 语言处理程序基础
  • Ai元人文:价值的“迷思”与“归真”——从家庭之爱到文明共生
  • MATLAB 数据可视化教程:从基础到进阶
  • 在ec2上部署qwen3-VL-2B模型
  • 37
  • Daily Scrum 2025.11.12
  • 完整教程:mit6s081 lab8 locks
  • 软件工程学习日志2025.11.12
  • [集训队互测 2025] 火花 做题记录