USACO The Castle(flood fill)

题目请点我

题解:

这道题真的好蛋疼啊,首先题意不好理解,搞了半天复杂的要死,有那么多要求,还要求那么多东西,做到一半都不想做了。。。感觉没什么技术含量,还做起来死费劲儿。但是强迫症非得按顺序做题啊,最后还是一点点把它给调出来了,说什么flood fill,其实也就是那么回事,没什么算法上的技巧,就是见招拆招的感觉。。。

题意搞懂再做题,题意,不谢!

第一步:根据他的规则把房间画出来,遍历一遍把每个节点四面的墙给补上;

第二步:深搜;

目的1:记录深搜的次数,房间数;

目的2:记录深搜的深度,最大房间面积;

目的3:把属于同一棵树的节点标记起来,也就是染色的过程,为下一步打通房间铺路;

注意:在深搜的过程中搜的深度要注意如何保存,会有分叉以及分叉后再汇合的情况出现,我是设置了一个全局变量deep来记录深度;

第三步:打墙;

题目说了,只能打一次,而且还有规则,先紧着西边的选,如果同样靠西要先紧着南边的选,所以要注意遍历的方向。打墙的时候就凸显之前标色的重要性了,首先得找到墙,然后墙两边的颜色还要不一样,从下往上,从左往右遍历一遍找到最优解。

PS:注意数组大小。

代码实现:

/*
ID: eashion
LANG:C++
TASK:castle
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAX 55

using namespace std;

int N,M;
int Sum;
int Size;
int deep;
int BSize;
int bx,by;
int color;
int Csize[MAX*MAX];
char oritation;
int maze[MAX][MAX];
int dx[4] = {1,0,-1,0};
int dy[4] = {0,-1,0,1};
int castle[MAX*3][MAX*3];
void solve();
void dfs(int x,int y,int col);
void Break();
int main()
{
    freopen("castle.in","r",stdin);
    freopen("castle.out","w",stdout);
    scanf("%d%d",&M,&N);
    for( int i = 1; i <=N; i++ ){
        for( int j = 1; j <= M; j++ ){
            scanf("%d",&maze[i][j]);
        }
    }
    solve();
    return 0;
}

void solve(){
    Sum = 0;
    Size = 0;
    BSize = 0;
    color = 2;
    memset(Csize,0,sizeof(Csize));
    memset(castle,0,sizeof(castle));
    //补墙,用到了&运算
    for( int i = 1; i <= N; i++ ){
        for( int j = 1; j <= M; j++ ){
            int tx = i*2-1;
            int ty = j*2-1;
            if( (maze[i][j]&1) == 1 ){
                castle[tx][ty-1] = 1;
            }
            if( (maze[i][j]&2) == 2 ){
                castle[tx-1][ty] = 1;
            }
            if( (maze[i][j]&4) == 4 ){
                castle[tx][ty+1] = 1;
            }
            if( (maze[i][j]&8) == 8 ){
                castle[tx+1][ty] = 1;
            }
        }
    }
    //补四面的墙
    for( int i = 0; i <= 2*N; i++ ){
        castle[i][0] = 1;
    }
    for( int i = 0; i <= 2*N; i++ ){
        castle[i][2*M] = 1;
    }
    for( int i = 0; i <= 2*M; i++ ){
        castle[0][i] = 1;
    }
    for( int i = 0; i <= 2*M; i++ ){
        castle[2*N][i] = 1;
    }
    //补节点处的墙,其实也不太会访问到
    for( int i = 2; i <= 2*N; i+=2 ){
        for( int j = 2; j <= 2*M; j+=2 ){
            castle[i][j] = 1;
        }
    }
//    for( int i = 0; i <= 2*N; i++ ){
//        for( int j = 0; j <= 2*M; j++ ){
//            printf("%d",castle[i][j]);
//        }
//        printf("\n");
//    }
    //深搜
    for( int i = 1; i <= N; i++ ){
        for( int j = 1; j <= M; j++ ){
            int tx = i*2-1;
            int ty = j*2-1;
            deep = 0;
            if( castle[tx][ty] == 0 ){
                dfs(tx,ty,color++);
                Csize[color-1] = deep;
                Sum++;
                Size = max(Size,deep);
            }
        }
    }
    //打墙
    Break();
    printf("%d\n",Sum);
    printf("%d\n",Size);
    printf("%d\n",BSize);
    printf("%d %d %c\n",bx,by,oritation);
}

void dfs(int x,int y,int col){
    //每进入一次深度+1
    deep++;
    //标色
    castle[x][y] = col;
    for( int i = 0; i < 4; i++ ){
        int nx = x+dx[i];
        int ny = y+dy[i];
        int nnx = nx+dx[i];
        int nny = ny+dy[i];
        //必须保证两个同时为0,因为下个节点可能会已经被染色,导致重复染色
        if( castle[nx][ny] == 0 && castle[nnx][nny] == 0 ){
            castle[nx][ny] = col;
            dfs(nnx,nny,col);
        }
    }
    return ;
}

void Break(){
    //注意遍历顺序
    for( int j = 0; j <= 2*M; j++ ){
        for( int i = 2*N; i >= 0; i-- ){
            if( castle[i][j] == 1 ){
                int ux,uy;
                int dx,dy;
                int rx,ry;
                int lx,ly;
                ux = i-1,uy = j;
                dx = i+1,dy = j;
                rx = i,ry = j+1;
                lx = i,ly = j-1;
                //上下打通
                if( ux >= 0 && dx <= 2*N && castle[ux][uy]!=castle[dx][dy] ){
                    int tmp = Csize[castle[ux][uy]]+Csize[castle[dx][dy]];
                    if( BSize < tmp ){
                        BSize = tmp;
                        bx = (dx+1)/2;
                        by = (dy+1)/2;
                        oritation = 'N';
                    }
                }
                //左右打通
                if( ly >= 0 && ry <= 2*M && castle[lx][ly]!=castle[rx][ry] ){
                    int tmp = Csize[castle[lx][ly]]+Csize[castle[rx][ry]];
                    if( BSize < tmp ){
                        BSize = tmp;
                        bx = (lx+1)/2;
                        by = (ly+1)/2;
                        oritation = 'E';
                    }
                }
                //把上下放前面,而且严格BSize < tmp,保证了若有可能先打‘N’
            }
        }
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-02 22:45:13

USACO The Castle(flood fill)的相关文章

洪水填充(Flood fill)算法

从一个起始节点开始把附近与其连通的节点提取出或填充成不同颜色颜色,直到封闭区域内的所有节点都被处理过为止,是从一个区域中提取若干个连通的点与其他相邻区域区分开(或分别染成不同颜色)的经典算法. 因为其思路类似洪水从一个区域扩散到所有能到达的区域而得名.在GNU Go和扫雷中,Flood Fill算法被用来计算需要被清除的区域. 洪水填充算法接受三个参数:起始节点,目标节点特征和针对提取对象要执行的处理. 目前有许多实现方式,基本上都显式的或隐式的使用了队列或者栈. 洪水填充算法实现最常见有四邻域

SSOJ 2316 面积【DFS/Flood Fill】

题目描述 编程计算由“1”号围成的下列图形的面积.面积计算方法是统计1号所围成的闭合曲线中点的数目. 如图所示,在10*10的二维数组中,“1”围住了15个点,因此面积为15. 题目大意:对于给定的10*10的01矩阵,请问有多少个0被1包围了?(包围是指不能由上下左右通向边缘)本文来源于OIER博客,原文出处:http://www.oier.cc/ssoj2316%E9%9D%A2%E7%A7%AF/ 解题思路 图形学中Flood Fill是满水法填充,是用来填充区域的.就好比在一个地方一直到

[LeetCode] Flood Fill 洪水填充

An image is represented by a 2-D array of integers, each integer representing the pixel value of the image (from 0 to 65535). Given a coordinate (sr, sc) representing the starting pixel (row and column) of the flood fill, and a pixel value newColor,

733. Flood Fill

An image is represented by a 2-D array of integers, each integer representing the pixel value of the image (from 0 to 65535). Given a coordinate (sr, sc) representing the starting pixel (row and column) of the flood fill, and a pixel value newColor,

733. Flood Fill 简单型染色问题

[抄题]: An image is represented by a 2-D array of integers, each integer representing the pixel value of the image (from 0 to 65535). Given a coordinate (sr, sc) representing the starting pixel (row and column) of the flood fill, and a pixel value newC

733. Flood Fill - Easy

An image is represented by a 2-D array of integers, each integer representing the pixel value of the image (from 0 to 65535). Given a coordinate (sr, sc) representing the starting pixel (row and column) of the flood fill, and a pixel value newColor,

CF 1114 D. Flood Fill

D. Flood Fill 链接 题意: 一个颜色序列,每个位置有一个颜色,选择一个起始位置,每次可以改变包含这个位置的颜色段,将这个颜色段修改为任意一个颜色, 问最少操作多少次.n<=5000 分析: 区间dp. dp[i][j][0/1]表示当前的区间是l~r,把这一段变成一个颜色的最少次数,最后一个改变的颜色是最左边/最右边的一段. 代码: #include<cstdio> #include<algorithm> #include<cstring> #inc

Codeforces Round #538 (Div. 2) D. Flood Fill 【区间dp || LPS (最长回文序列)】

任意门:http://codeforces.com/contest/1114/problem/D D. Flood Fill time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a line of nn colored squares in a row, numbered from 11 to nn f

CodeForces - 1114D Flood Fill (区间dp)

You are given a line of nn colored squares in a row, numbered from 11 to nn from left to right. The ii-th square initially has the color cici. Let's say, that two squares ii and jj belong to the same connected component if ci=cjci=cj, and ci=ckci=ck