题解 洛谷P1457 【城堡 The Castle】
这道题,看似很烦,无从下手,但其实只要用位运算和联通快就能水过了呀。
首先,输入大意是把一个数拆成二进数的相加,分别表示 \((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】的更多相关文章
- 洛谷P1457 城堡 The Castle
P1457 城堡 The Castle 137通过 279提交 题目提供者该用户不存在 标签USACO 难度提高+/省选- 提交 讨论 题解 最新讨论 暂时没有讨论 题目描述 我们憨厚的USACO ...
- 洛谷 P1457 城堡 The Castle 解题报告
P1457 城堡 The Castle 题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张"幸运爱尔兰" ...
- 洛谷 P1457 城堡 The Castle
P1457 城堡 The Castle 题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张“幸运爱尔兰”(一种彩票).结果这 ...
- 洛谷—— P1457 城堡 The Castle
https://www.luogu.org/problem/show?pid=1457 题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特 ...
- 题解 洛谷P5018【对称二叉树】(noip2018T4)
\(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...
- 题解 洛谷 P3396 【哈希冲突】(根号分治)
根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...
- 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)
题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...
- 题解-洛谷P4229 某位歌姬的故事
题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...
- 题解-洛谷P4724 【模板】三维凸包
洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...
随机推荐
- 21 javaweb开发--bug调试技巧
1.当修改代码后,测试时没有任何效果 解决方案:换个浏览器试试,可能是浏览器缓存的原因.
- Linux学习-基本命令文件操作
终端 1.多个终端 连接linux的客户端可以理解为终端. 命令:tty查看终端 2.不同终端之间的通讯 [root@wyx wyx]# echo 123 > /dev/pts/1 把123发给 ...
- PMBOK(第六版) PMP备考知识总汇!
记录本人学习PMBOK第六版的学习笔记. 备考知识总汇! PMBOK序章 PMP备考指南之相关事项介绍 PMP备考指南之第一章:引论 PMP备考指南之第二章:项目运作环境 PMP备考指南之第三章:项目 ...
- Linux中进行jdk的安装+Tomcat安装+mysql的安装
1.上传所需要的文件(这里事先准备好了jdk和tomcat的安装包,mysql需要在线安装) jdk的安装包名称:jdk-8u151-linux-x64.tar.gz tomcat 的安装包名称:ap ...
- 92. 反转链表 II
反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明: 1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NULL, m ...
- struct,interface,method
struct类型,值传递的 声明 struct { name string age int } //几种声明使用方式: var P person // P现在就是person类型的变量了 P.name ...
- flink ETL数据处理
Flink ETL 实现数据清洗 一:需求(针对算法产生的日志数据进行清洗拆分) 1. 算法产生的日志数据是嵌套json格式,需要拆分 2.针对算法中的国家字段进行大区转换 3.最后把不同类型的日 ...
- Python字符串格式化方式之format
format方式是在Python3引入了一个新的字符串格式化的方法,并且随后支持了Python2.7.这个新的字符串格式化方法摆脱了%操作符并且使得字符串格式化的语法更规范了.现在时候通过调用字符串对 ...
- VirtualBox导入OVA文件文档教程
1 2 修改框住的路径,最好不要在C盘 3 取消检查更新 4 5 6 7 8 9 10 11 等待加载完成:加载完成后 OVA文件导入成功 作者:含笑半步颠√ 博客链接:https://www.cnb ...
- tkinter学习笔记_03
6.单选框 Radiobutton import tkinter as tk root = tk.Tk() root.title("xxx") root.geometry('2 ...