USACO 2.1 The Castle

9 篇文章 0 订阅

        最近为了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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值