这道题,看似很烦,无从下手,但其实只要用位运算联通快就能水过了呀。

首先,输入大意是把一个数拆成二进数的相加,分别表示 \((i,j)\) 东南西北是否有墙。\(1\) 表示西,\(2\) 表示北,\(4\) 表示东,\(8\) 表示南。

第一种方法,你可以写 \(15\) 个 \(\operatorname{if}\),分别枚举 \(15\) 种情况,然后求出它的二进制拆分。

第二种比较简单的方法,我们可以尝试用位运算来解决。

先来了解一下位运算中的 \(\&\)。它做的是一种运算,对于两个 \(2\) 进制,当它们的某一位都是 \(1\),则返回 \(1\),否则返回 \(0\)。

举个栗子:\(3\&11=0011\&1011=0011\)

好了,诸如 \(1,2,4,8……\) 这样的数,它们在二进制中都只能拆成\(0001,0010,0100,1000……\)。假如我们要知道某个数中能否拆成一个\(2^n\),那我们只需要拿它的二进数与 \(2^n\) 的二进制进行比较。如果它们有共同的\(1\),则说明 \(2^n\) 是其拆出来的一个数。

那么接下来,即可考虑设一个数组 \(a[i][j][k]\),表示对于某个房间 \((i,j)\),其 \(k\) 方向是否有墙。

注意 \(0\) 表示西方,\(1\) 表示北方,\(2\) 表示东方,\(3\) 表示南方。

const int dir[5][5]={
{0,-1},{-1,0},{0,1},{1,0}//方向
};
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x;
cin>>x;
if(x&1)a[i][j][0]=1;
if(x&2)a[i][j][1]=1;
if(x&4)a[i][j][2]=1;
if(x&8)a[i][j][3]=1;
//位运算,1表示有墙
}
}

下面可以切入主程序了。

  • 对于第一二问,题目是要求联通快的个数以及最大的联通快的面积。

这个很简单,我们用\(dfs\)遍历所有点。每个点扩展出他的所有联通快,并且记录最大的面积即可。

  • 对于第三四问,题目是要我们找拆掉哪面墙才能使得新房间的大小尽可能大。

其实说白了还是枚举,我们要暴搜所有的墙。假如拆掉了 \((i,j)\) 北面的墙,则 \((i-1,j)\) 南面的墙也会被拆掉。假如拆掉了 \((i,j)\) 东面的墙,则 \((i+1,j)\) 西面的墙也会被拆掉。

故在拆墙的过程中,可能会影响到许多的房间,这是我们要特殊考虑的。

\(\operatorname{Code}:\)

#include<bits/stdc++.h>
using namespace std;
int n,m,a[60][60][10],h[60][60];
int sum,area,max_area;
int ansx,ansy,ansfx;
const int dir[5][5]={
{0,-1},{-1,0},{0,1},{1,0}//方向
};
void dfs(int x,int y){
h[x][y]=1,area++;
for(int i=0;i<4;i++){
if(a[x][y][i])continue;//有墙!
int tx=x+dir[i][0];
int ty=y+dir[i][1];//下一个点
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&h[tx][ty]==0){
//未超边界且可以走
dfs(tx,ty);
}
}
}
void find_(int x,int y,int fx){//查找联通快
memset(h,0,sizeof(h));//清零!
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(h[i][j])continue;
area=0;
dfs(i,j),sum++;//查找联通快
if(area>max_area){
max_area=area;//更新最大面积
ansx=x,ansy=y,ansfx=fx;//记录坐标,方向
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>m>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x;
cin>>x;
if(x&1)a[i][j][0]=1;
if(x&2)a[i][j][1]=1;
if(x&4)a[i][j][2]=1;
if(x&8)a[i][j][3]=1;
//位运算,1表示有墙
}
}
find_(0,0,0);
cout<<sum<<endl;
cout<<max_area<<endl;
max_area=0;
for(int j=1;j<=m;j++){
for(int i=n;i>=1;i--){
for(int k=1;k<3;k++){
if(a[i][j][k]==0)continue;
a[i][j][k]=0;
if(k==1)a[i-1][j][3]=0;
if(k==2)a[i][j+1][0]=0;
find_(i,j,k);
a[i][j][k]=1;
if(k==1)a[i-1][j][3]=1;
if(k==2)a[i][j+1][0]=1;
}
}
}
cout<<max_area<<endl;
char ansch;
if(ansfx==1)ansch='N';
else ansch='E';//判断方向
cout<<ansx<<" "<<ansy<<" "<<ansch<<endl;
return 0;
}

\(\operatorname{Update}\) \(\operatorname{On}\) \(\operatorname{2019.05.17}\)

题解 洛谷P1457 【城堡 The Castle】的更多相关文章

  1. 洛谷P1457 城堡 The Castle

    P1457 城堡 The Castle 137通过 279提交 题目提供者该用户不存在 标签USACO 难度提高+/省选- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 我们憨厚的USACO ...

  2. 洛谷 P1457 城堡 The Castle 解题报告

    P1457 城堡 The Castle 题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张"幸运爱尔兰" ...

  3. 洛谷 P1457 城堡 The Castle

    P1457 城堡 The Castle 题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张“幸运爱尔兰”(一种彩票).结果这 ...

  4. 洛谷—— P1457 城堡 The Castle

    https://www.luogu.org/problem/show?pid=1457 题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特 ...

  5. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  6. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  7. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  8. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

  9. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

随机推荐

  1. 根据本地/服务器时间获取指定时区时间 new Date指定时区时间

    1.代码 function getTimeByTimeZone(timeZone){ var d=new Date(); localTime = d.getTime(), localOffset=d. ...

  2. java8新特性六-Optional 类

    Optional 类是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. Optional 是个容器:它可以保存类型T的值,或者仅仅保 ...

  3. 启动3ds Max报 d3dx9_43.dll丢失 解决方法

    d3dx9_43.dll文件与Microsoft DirectX关联.负责启动基于Windows的游戏和高级图形程序. 在360安全卫士上搜索了 DirectX 下载了这个修复工具 运行应用 点击修复 ...

  4. javascript——常用事件总结

      Event对象:Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 事件标签属性 当以下情况发生时,出现此事件 onabort 图像加载被中断 ...

  5. PHP提取中英文首字母的方法(首字母索引)

    function Getzimu($str) { $str= iconv("UTF-8","gb2312", $str);//如果程序是gbk的,此行就要注释掉 ...

  6. WEB前后端分离开发中的验证与安全问题

    登录验证以及安全问题: 1.请求接口全部用post方式,在后端判断请求方式是否为post 2.登录密码等敏感信息要加密后传输,如用RSA(支付宝里可下载公私钥生成工具),客户端公钥加密,传到服务器后再 ...

  7. python学习-66 面向对象3 - 多态

    多态 1.什么是多态 由不同的类实例化得到的对象,调用同一个方法,执行的逻辑不同. 举例: class H2O: def __init__(self,type,tem): self.type = ty ...

  8. 继承 多态 封装 Python面向对象的三大特性

    1. 封装: 把很多数据封装到⼀个对象中. 把固定功能的代码封装到⼀个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想. 具体的情况具体分析.  那这个也可以被称为封装. 2. 继承: 两个 ...

  9. char * const * (*a) (int b)

    char * const * (*a) (int b), 按照c++ program language的读法,从右往左读,* 读作pointer to 把(*a) (int b看作整体, (*a) ( ...

  10. iOS核心动画(专用图层篇)

    之前的文章我们了解了Core Animation中图层的一些基础知识.没有看过的传送门在此: iOS核心动画基础篇 那么在了解了这些基础知识之后,接下来进入专用图层的了解 苹果为了方便和性能,封装了几 ...