首页 > 其他分享 >P1457 [USACO2.1] 城堡 The Castle 题解

P1457 [USACO2.1] 城堡 The Castle 题解

时间:2023-10-11 21:46:37浏览次数:43  
标签:P1457 int 题解 pos yy wall xx mp USACO2.1

分析

感觉没有蓝题难度

一道 bfs 题目,相较于大部分 bfs 题,它较为复杂,但分析一下还是很好水过的。

建立墙时,可以用三维数组,\(wall_{~i, ~j, ~pos}\) 表示 第 \(i\) 行第 \(j\) 列 \(pos\) 方向有墙。

观察发现,\(8 = 2^3,4 = 2^2,2 = 2^1,1 = 2^1\),于是可以用位运算快速储存。这里给出代码方便理解。

void build(int x, int y, int w)
{
	if (w & 8)wall[x][y][0] = 1;
	if (w & 4)wall[x][y][1] = 1;
	if (w & 2)wall[x][y][2] = 1;
	if (w & 1)wall[x][y][3] = 1;
}

接下来就是 bfs 的过程,在 bfs 时,保存下答案,以及这个房间的编号和这个房间的大小,对于接下来的拆墙有用。

对于拆墙,前面保存的编号和房间大小有了作用,遍历行和列,并只看东墙和北墙,如果墙后与当前格子的编号相同,直接跳过,否则更新答案。

注意:遍历时先遍历列,再遍历行,然后选择北墙,最后是东墙,因为题目说明西边的更优,然后是更南的,最后同一格子下,北边的更优,详细的可以看代码说明。

Accepted Code

/*Code By Manipula*/
#include <bits/stdc++.h>
using namespace std;
const int N = 55;
int mp[N][N], wall[N][N][4], space[N], num, ans1, ans2, ax, ay, n, m;
int fx[4] = {1, 0, -1, 0}, fy[4] = {0, 1, 0, -1};
char dir;
void build(int x, int y, int w)
{
	if (w & 8)wall[x][y][0] = 1;
	if (w & 4)wall[x][y][1] = 1;
	if (w & 2)wall[x][y][2] = 1;
	if (w & 1)wall[x][y][3] = 1;
}
struct Node{
	int x, y;
};
queue<Node> q;
void bfs(int sx, int sy)
{
	q.push((Node){sx, sy});
	mp[sx][sy] = ++num;//记编号
	int ret = 1;
	while (!q.empty())
	{
		int x = q.front().x, y = q.front().y; q.pop();
		for (int i = 0; i < 4; i++)
		{
			int xx = x + fx[i], yy = y + fy[i];
			if (xx < 1 || xx > n || yy < 1 || yy > m)continue;
			if (mp[xx][yy] || wall[x][y][i])continue;
			mp[xx][yy] = num;
			q.push((Node){xx, yy});
			ret++;
		}
	}
	ans1 = max(ans1, ret);
	space[num] = ret;
}
int main()
{
	cin >> n >> m; n ^= m ^= n ^= m;//交换一下,个人喜欢 n 为行数, m 为列数
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
		{
			int w; cin >> w;
			build(i, j, w);
		}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			if (!mp[i][j])bfs(i, j);
	for (int j = 1; j <= m; j++)//选择最西的
		for (int i = n; i >= 1; i--)//选择最南的
			for (int pos = 2; pos >= 1; pos--)//优先选择北边的墙
				if (wall[i][j][pos])
				{
					int xx = i + fx[pos], yy = j + fy[pos];
					if (mp[i][j] == mp[xx][yy])continue;//特判,如果他们的编号相同就不计算
					if (space[mp[i][j]] + space[mp[xx][yy]] > ans2)
					{
						ans2 = space[mp[i][j]] + space[mp[xx][yy]];
						ax = i; ay = j; dir = (pos == 1 ? 'E' : 'N');
					}
				}
	cout << num << endl << ans1 << endl;
	cout << ans2 << endl << ax << " " << ay << " " << dir;
	return 0;
}

标签:P1457,int,题解,pos,yy,wall,xx,mp,USACO2.1
From: https://www.cnblogs.com/Manipula/p/17758258.html

相关文章

  • Ubuntu无法联网问题解决
    前言会有不同种原因导致系统无法联网,我遇到的可能只是其中一种,建议多问问ChatGPT,每一步遇到的问题问问人家应该能解决我遇到的情况是,之前一直能联网,然后一段时间不登就连不上网,然后又好了,然后又连不上网因此也把我这种情况的解决方案记录一下,以备不时之需   解决步骤......
  • Shuffle 题解
    Shuffle题目大意给定一个长度为\(n\)的01序列\(a\),你可以进行至多一次以下操作:选定\(a\)的一个连续段,满足连续段内恰好有\(k\)个\(1\),将该连续段任意排列。问能产生多少种不同的01序列。思路分析(这题\(n\)完全可以开到\(10^6\)或是\(10^7\),因为存在\(O(......
  • Hadoop问题解决(5)
    当一个HDFS系统同时处理许多个并行的put操作,往HDFS上传数据时,有时候会出现dfsclient端发生socket链接超时的报错,有的时候甚至会由于这种原因导致最终的put操作失败,造成数据上传不完整。log类似如下:Alldatanodes ***arebad.Aborting...类似这样的错误,常常会在并行的put操作......
  • Debian12安装MySQL8实践及问题解决方案
    Debian12安装MySQL数据库,常规操作:sudoaptsearchmysql&sudoaptinstallmysql,肯定是行不通的,因为没有安装包。把我的安装过程以及遇到问题的解决方案记录下来,供大家借鉴。第一步更新系统、下载软件包命令如下:sudoaptupdatewgethttps://dev.mysql.com/get/mysql-apt-co......
  • 【题解 P3586】 LOG
    [POI2015]LOG题目描述维护一个长度为\(n\)的序列,一开始都是\(0\),支持以下两种操作:Uka将序列中第\(k\)个数修改为\(a\)。Zcs在这个序列上,每次选出\(c\)个正数,并将它们都减去\(1\),询问能否进行\(s\)次操作。每次询问独立,即每次询问不会对序列进行修改。输......
  • 题解 AcWing 359.创世纪
    题目描述给你一个\(n\)个点\(n\)条边的有向图,若选了当前节点,那么当前节点的儿子节点至少有一个不能选。求最多能选多少个点。具体思路显然是一棵基环树,因此考虑基环树dp。我们先不管环的条件,先考虑朴素的树形dp。设\(f_{x,0}\)表示\(x\)节点不选,最多可以选多少个......
  • 网络规划设计师真题解析--位示图大小计算
    假设某计算机的字长为32位,该计算机文件管理系统磁盘空间管理采用位示图,记录磁盘的使用情况,若磁盘的容量为300GB,物理块的大小为4MB,那么位示图的大小为(2)个字。(2020年)(2)A.2400 B.3200 C.6400 D.9600答案:A解析:已知磁盘容量为300GB,物理块大小为4MB则计算物理块数=300*1024/4=76800(个)位......
  • 题解: CF768D Jon and Orbs
    题解:CF768DJonandOrbs一句话体面:有k种不同的物品,每天等概率任取一种(不一定是新的种类)。q组询问,每组给出一个p,问取完这k件物品的概率不小于\(\frac{p}{2000}\)的最小天数不用说,肯定是概率DP了1.定义:\(f_{i,j}\)表示前\(i\)天选取了\(j\)种物品的概率(\(P.S.\)该定义不......
  • 题解 DIFERENC - DIFERENCIJA
    题目描述给出一个长度为\(n\)的序列\(a_i\),求出下列式子的值:\[\sum_{i=1}^n\sum_{j=i}^n(\max\limits_{i\lek\lej}a_k-\min\limits_{i\lek\lej}a_k)\]即定义一个子序列的权值为序列内最大值与最小值的差。求出所有连续子序列的权值和。具体思路暴力思路很好......
  • p4801题解
    解题思路:确实是一道很好的贪心,但由于加上了水这个影响因素,使题目复杂度上升了不少。(考虑的东西多了嘛)输个入。对饼干温度无脑排序。求最小值。求最大值(用双指针做,后面会讲)。解题过程:先输入(这个步骤就不用我讲了)inta[1000005];longlongn,ws;longlongmin......