当前位置: 首页 > news >正文

ssl1104-USACO 2.1城堡(foodfill)【图论,广搜】

前言

由于这道题比较难,有不好描述,我就直接贴题目了。

Description

以一个几乎超乎想像的运气,农民约翰在他的生日收到了一张爱尔兰博彩的奖券。
这一张奖券成为了唯一中奖的奖券。
农民约翰嬴得爱尔兰的乡下地方的一个传说中的城堡。
吹牛在他们威斯康辛州不算什么,农民约翰想告诉他的牛所有有关城堡的事。
他想知道城堡有多少房间,而且最大的房间有多大。
事实上,他想去掉一面墙来制造一个更大的房间。
你的任务是帮助农民约翰去了解正确房间数目和大小。
城堡的平面图被分为 M(wide)*N(1 <=M,N<=50)个小正方形。
每个这样的小正方形有0到4面墙。
城堡在它的外部边缘总是有墙壁的,好遮挡风雨。
考虑这注解了一个城堡的平面图:
原图
例子的城堡的大小是7 x 4。
一个 “房间”是平面图上有连接的”小正方形”的集合。
这个平面图包含五个房间。(它们的大小是9,7,3,1, 和 8 排列没有特别的顺序)。
移除被箭作记号的墙壁来合并两个房间来制造最大的可能房间(移除一面墙所能产生的)。
城堡总是至少有二个房间并且总是有一面墙壁以可能被移除。

Input

地图以一个表格来储存,每个数字描述一个小正方形,N行每行M个数来描述这个平面图。
输入顺序符合那个在上面例子的编号方式。
每个描述小正方形的数字说明小正方形的四面的墙的分布情况,它是下面4个数的和:
1: 在西面有墙
2: 在北面有墙
4: 在东面有墙
8: 在南面有墙
内部的墙壁是会被定义两次;小正方形(1,1)南面的墙也被指出是小正方形(2,1)北面的墙。
第 1 行: 二个被空格分开的整数: M 和 N
第 2 到 N+1 行: M x N 个整数,每行M个。

Output

输出包含一些行:
第 1 行: 城堡的房间数目。
第 2 行: 最大的房间的大小
第 3 行: 移除一面墙能得到的最大的房间的大小
第 4 行: 移除哪面墙
选择最佳的墙来移除,(选择最靠西的,如果仍然不能确定,再选择最靠南的。编者注:墙的位置应该由它的中点来定义)
(【原文】Choose the optimal wall to remove from the set of optimal walls by choosing the wall farther to the west (and then, if still tied, farthest to the south).)
墙壁由它在相邻的小正方形的西部或南方来命名
最后一行一定要有回车

Sample Input

7 4
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13

Sample Output

5
9
16
4 1 E


解题思路

用广搜求出前2个值。求出每个小方格的对应的房间的大小,然后枚举一下破坏哪堵墙求最大值。


代码

#include<cstdio>
#include<iostream>
using namespace std;
const int W=0,N=1,E=2,S=3;//常量
int dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};
//搜索方向
bool a[51][51][4];//记录有没有墙
int head,tail,walk[51][51],ft[2501],mn,maxs,x,n,m;
int state[2501][2],c;
void bfs(int x,int y)
{
    c++;
    //标记房间号
    head=0;
    tail=1;
    state[1][0]=x;
    state[1][1]=y;
    walk[x][y]=c;
    //初始化
    do
    {
        head+=1;
        for (int i=0;i<4;i++) 
        {
          x=state[head][0]+dx[i];
          y=state[head][1]+dy[i];
          int zx,zy;
          zx=state[head][0];
          zy=state[head][1];
          if (walk[x][y]==0 && !a[zx][zy][i] && x<=n && y<=m && x>=1 && y>=1)
          {
            tail++;
            state[tail][0]=x;
            state[tail][1]=y;
            walk[x][y]=c;//归入当前房间
          }
        }
    }while (head<tail);
} 
int main()
{
    scanf("%d%d",&m,&n);    
    for (int i=1;i<=n;i++)
      for (int j=1;j<=m;j++)
      {
        scanf("%d",&x);
        if (x>=8) {a[i][j][S]=true;a[i+1][j][N]=true;x-=8;}//南墙
        if (x>=4) {a[i][j][E]=true;a[i][j+1][W]=true;x-=4;}//东墙
        if (x>=2) {a[i][j][N]=true;a[i-1][j][S]=true;x-=2;}//北墙
        if (x>=1) {a[i][j][W]=true;a[i][j-1][E]=true;x-=1;}//西墙
      }   

    for (int i=1;i<=n;i++)
      for (int j=1;j<=m;j++)
        if (!walk[i][j])
        {
            mn++;//房间总数
            bfs(i,j);//搜索
            maxs=max(maxs,tail);
            //求最大房间
            ft[c]=tail;//记录房间大小
        }
    printf("%d\n%d\n",mn,maxs);//输出
    maxs=0;
    x=0;
    int y=0;
    char wall='0';
    //根据题目要求我们可以得知只有可能破坏N或E墙
    for (int j=1;j<=m;j++)
      for (int i=n;i>=1;i--)    
      {
        if (i-1>=1 && a[i][j][N] && walk[i][j]!=walk[i-1][j] && ft[walk[i][j]]+ft[walk[i-1][j]]>maxs)
        //判断如果该方向有墙而且不属于同一个房间
          {maxs=ft[walk[i][j]]+ft[walk[i-1][j]];x=i;y=j;wall='N';}
          //同上
        if (j+1<=m && a[i][j][E] && walk[i][j]!=walk[i][j+1] && ft[walk[i][j]]+ft[walk[i][j+1]]>maxs)
          {maxs=ft[walk[i][j]]+ft[walk[i][j+1]];x=i;y=j;wall='E';}
      }
    printf("%d\n%d %d %c",maxs,x,y,wall);
}

转载于:https://www.cnblogs.com/sslwyc/p/9218627.html

相关文章:

  • C#多线程技术提高RabbitMQ消费吞吐率
  • 2017年总结的前端文章——border属性的多方位应用和实现自适应三角形
  • django之中间件
  • 推荐系统的基本概念及其在各个领域的应用
  • Linux 计划任务
  • 分布式系统事务一致性解决方案
  • Linux如何让进程在后台运行的三种方法详解
  • C#启动或停止 计算机中“服务”
  • Bootstarp学习
  • rsync远程同步
  • python基础-字符串
  • 2016级算法期末上机-A.简单·Bamboo's Fight with DDLs I
  • 图解 Java 内存模型
  • 【BZOJ2132】圈地计划(最小割)
  • 【Java基础】14、位与()操作与快速取模
  • 30秒的PHP代码片段(1)数组 - Array
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • Angular数据绑定机制
  • django开发-定时任务的使用
  • If…else
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • mysql_config not found
  • React as a UI Runtime(五、列表)
  • tab.js分享及浏览器兼容性问题汇总
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • vue的全局变量和全局拦截请求器
  • vue--为什么data属性必须是一个函数
  • 从伪并行的 Python 多线程说起
  • 机器学习中为什么要做归一化normalization
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 如何在GitHub上创建个人博客
  • Mac 上flink的安装与启动
  • ​MySQL主从复制一致性检测
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • #Linux(make工具和makefile文件以及makefile语法)
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (14)Hive调优——合并小文件
  • (145)光线追踪距离场柔和阴影
  • (2)STM32单片机上位机
  • (阿里云万网)-域名注册购买实名流程
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (蓝桥杯每日一题)love
  • (一)u-boot-nand.bin的下载
  • (译)2019年前端性能优化清单 — 下篇
  • (转)四层和七层负载均衡的区别
  • .bat文件调用java类的main方法
  • .NET Core Web APi类库如何内嵌运行?
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .NET多线程执行函数
  • .net和php怎么连接,php和apache之间如何连接
  • .sdf和.msp文件读取
  • /etc/sudoers (root权限管理)
  • ::什么意思
  • [ linux ] linux 命令英文全称及解释