USACO 2.1 The Castle

本文分享了作者使用C++进行复健训练的过程,通过刷题提升编程技能,具体介绍了如何利用FloodFill算法解决USACO兴趣题,并提供了代码实现细节。文章还分享了在处理数组边界时的小技巧,以及房间遍历部分采用的BFS迭代方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        最近为了C++的复健,开始刷USACO了,闲下来的时候做做兴趣题。写的是一些自己的想法,不一定是最佳方案,还请想要参考的人自己比对一下。


        这道题主要使用了官网之前提到的Flood Fill。

        先遍历所有房间,找出连起来的块标记好,到这里为止,算出了房间数和最大房间。再遍历一遍房间+标记,由于题目条件,所以只用敲掉北墙和东墙,从而求出敲掉一面墙后的最大值。


        数组的边界上我做了一个小trick,对于四周的边界多加了一行。这样在边界判断左右上下元素的时候,都不会越界。

        也算是给跟我一样讨厌数组越界的人提供个思路。


        对于房间遍历的部分,我用了BFS的迭代,对于每个被检查的房间,都检查它的四周,有没有与它相连的部分,有的话就迭代。

        在第一次遍历后,记录下来的是每一个房间所在块的大小、对每一个房间都做了代表块的标号。


        以下附上代码:

#include <iostream>
#include <fstream>
using namespace std;


const int MAXLEN = 53;
int height, width;
int walls[MAXLEN][MAXLEN];
int areas[MAXLEN][MAXLEN];
int flags[MAXLEN][MAXLEN];
int hstSize;
int roomNum = 0;
int maxSize = 0;
int maxModSize = 0;
int bi, bj;
char bd;


void findBlock(int i, int j)
{
    if (areas[i][j] != 0)
        return;

    int num = walls[i][j];
    areas[i][j] = -1;
    hstSize ++;

    if (num % 2 == 0)
        findBlock(i, j-1);
    if (num % 4 == 0 || num % 4 == 1)
        findBlock(i-1, j);
    if (num <= 3 || (num >= 8 && num <= 11))
        findBlock(i, j+1);
    if (num <= 7)
        findBlock(i+1, j);
}

void calArea()
{
    roomNum ++;
    maxSize = hstSize > maxSize ? hstSize : maxSize;

    int i, j, k;
    for (i = 1; i <= height; i ++) {
        for (j = 1; j <= width; j ++) {
            if (areas[i][j] == -1) {
                areas[i][j] = hstSize;
                flags[i][j] = roomNum;
                k ++;
            }
            if (k == hstSize)
                return;
        }
    }
}

void breakWall()
{
    int i, j;

    for (j = 1; j <= width; j ++) {
        for (i = height; i >= 1; i --) {
            if (flags[i][j] != flags[i-1][j]
                && areas[i][j] + areas[i-1][j] > maxModSize) {
                    maxModSize = areas[i][j] + areas[i-1][j];
                    bi = i;
                    bj = j;
                    bd = 'N';
            }
            if (flags[i][j] != flags[i][j+1]
                && areas[i][j] + areas[i][j+1] > maxModSize) {
                    maxModSize = areas[i][j] + areas[i][j+1];
                    bi = i;
                    bj = j;
                    bd = 'E';
            }
        }
    }
}

int main()
{
    ifstream fin ("castle.in");
    ofstream fout ("castle.out");

    int i, j;

    fin >> width >> height;
    for (i = 1; i <= height; i ++)
        for (j = 1; j <= width; j ++)
            fin >> walls[i][j];

    for (i = 1; i <= height; i ++) {
        for (j = 1; j <= width; j ++) {
            if (areas[i][j] != 0)
                continue;
            hstSize = 0;
            findBlock(i, j);
            calArea();
        }
    }

    breakWall();

    fout << roomNum << endl;
    fout << maxSize << endl;
    fout << maxModSize << endl;
    fout << bi << " " << bj << " " << bd << endl;
}


在P1458 USACO 2.1 有序分数 Ordered Fractions 的题目中,你需要处理一组分数,每个分数由两个整数表示,即分子m和分母d,然后对这些分数按照它们的小数形式进行非递减排序。以下是解决这个问题的一般步骤: 1. **创建结构体**: 定义一个包含分子和分母的结构体或类,例如在C++中可以是`struct Fraction { int numerator; int denominator; }`。 2. **转换为小数**: 对于每个分数,需要将其转换为浮点数以便进行比较。这可以通过除法操作 `float fraction = (float)m / d;` 来完成。 3. **比较函数**: 编写一个用于比较两个分数大小的函数,通常通过比较它们的小数形式。如果分数a小于b,则返回负数;等于则返回0;大于则返回正数。 ```cpp bool compareFractions(const Fraction &a, const Fraction &b) { return a.numerator * b.denominator > b.numerator * a.denominator; } ``` 4. **排序算法**: 使用适当的排序算法,如`std::sort`(对于C++),对分数数组进行排序。这里,你可以传递自定义的比较函数给`sort`,它会根据这个函数的规则对元素进行排序。 ```cpp std::vector<Fraction> fractions; // ... 添加分数到fractions列表中 std::sort(fractions.begin(), fractions.end(), compareFractions); ``` 5. **存储结果**: 排序完成后,数组`fractions`就包含了按照要求排列的分数。注意,由于原题可能要求输出的是字符串形式,因此在存储之前可能还需要遍历数组,将每个分数转换回字符串。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值