当前位置: 首页 > 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.gsyq.cn/news/47854.html

相关文章:

  • 文字识别系统代码
  • 微软2025年11月补丁星期二修复1个零日漏洞和63个安全漏洞
  • Can Large Language Models Detect Rumors on Social Media?
  • P13573 [CCPC 2024 重庆站] Pico Park
  • 手工安装gcc-13.3.0
  • 深入解析:Cookie、Session、JWT、SSO,网站与 APP 登录持久化与缓存
  • AT_arc111_f [ARC111F] Do you like query problems?
  • Ai元人文:价值的“迷思”与“归真”——从家庭之爱到文明共生
  • 日总结 26
  • Daily Scrum 2025.11.12
  • 完整教程:mit6s081 lab8 locks
  • Python梯度提升树、XGBoost、LASSO回归、决策树、SVM、随机森林预测中国A股上市公司数据研发操纵融合CEO特质与公司特征及SHAP可解释性研究|附代码数据
  • 2025商超照明/灯具/灯光源头厂家推荐榜:富明阳领衔,四大优质品牌凭技术与服务出圈,照亮商超经营新图景
  • 2025密集型/智能/防潮防腐/多层抽屉式/切片蜡块柜推荐榜:北京中宝元五星领跑 高容量智能存储方案成实验室优选
  • 专题:2025AI时代的医疗保健业:应用与行业趋势研究报告|附130+份报告PDF、数据、可视化模板汇总下载
  • 详细介绍:python编程基础知识
  • 计算机网络 —— 交换机 —— 二层交换机 or 三层交换机
  • P7912 [CSP-J 2021] 小熊的果篮
  • 数据结构与算法:动态规划的深度探讨 - 指南
  • 第六章蓝墨云班习题
  • [network] IPv4 vs. IPv6 address pool
  • 【为美好CTF献上祝福】浅学花指令
  • 能耗在线监测体系:革新能源管理模式,助推企业节能减排
  • 2025/11/14
  • 一份用pyhon生成word/wps蓝墨云班题库的代码
  • 公开仓库中的哈希值暴露安全风险分析
  • Kibana基本命令操作
  • 如何在 .NET 中使用 SIMD
  • Linux shell映射表(变量的变量)
  • Java 集合-Set