题目描述

我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张“幸运爱尔兰”(一种彩票)。结果这张彩票让他获得了这次比赛唯一的奖品——坐落于爱尔兰郊外的一座梦幻般的城堡!

喜欢吹嘘的农夫约翰立刻回到有着吹嘘传统的威斯康辛老家开始吹嘘了, 农夫约翰想要告诉他的奶牛们关于他城堡的一切。他需要做一些吹嘘前的准备工作:比如说知道城堡有多少个房间,每个房间有多大。另外,农夫约翰想要把一面单独的墙(指两个单位间的墙)拆掉以形成一个更大的房间。 你的工作就是帮农夫约翰做以上的准备,算出房间数与房间的大小。

城堡的平面图被划分成M*N(1 <=M,N<=50)个正方形的单位,一个这样的单位可以有0到4面墙环绕。城堡周围一定有外墙环绕以遮风挡雨。(就是说平面图的四周一定是墙。)

请仔细研究下面这个有注解的城堡平面图:

友情提示,这个城堡的平面图是7×4个单位的。一个“房间”的是平面图中一个由“#”、“-”、“|”围成的格子(就是图里面的那一个个的格子)。比如说这个样例就有5个房间。(大小分别为9、7、3、1、8个单位(排名不分先后))

移去箭头所指的那面墙,可以使2个房间合为一个新房间,且比移去其他墙所形成的房间都大。(原文为:Removing the wall marked by the arrow merges a pair of rooms to make the largest possible room that can be made by removing a single wall. )

城堡保证至少有2个房间,而且一定有一面墙可以被移走。

输入输出格式

输入格式:

第一行有两个整数:M和N 城堡的平面图用一个由数字组成的矩阵表示,一个数字表示一个单位,矩阵有N行M列。输入与样例的图一致。

每一个单位的数字告诉我们这个单位的东西南北是否有墙存在。每个数字是由以下四个整数的某个或某几个或一个都没有加起来的。

1: 在西面有墙

2: 在北面有墙

4: 在东面有墙

8: 在南面有墙

城堡内部的墙会被规定两次。比如说(1,1)南面的墙,亦会被标记为(2,1)北面的墙。

输出格式:

输出包含如下4行:

第 1 行: 城堡的房间数目。

第 2 行: 最大的房间的大小

第 3 行: 移除一面墙能得到的最大的房间的大小

第 4 行: 移除哪面墙可以得到面积最大的新房间。

选择最佳的墙来推倒。有多解时选最靠西的,仍然有多解时选最靠南的。同一格子北边的墙比东边的墙更优先。

用该墙的南邻单位的北墙或西邻单位的东墙来表示这面墙,方法是输出邻近单位的行数、列数和墙的方位("N"(北)或者"E"(东))。

输入输出样例

输入样例#1: 复制

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
输出样例#1: 复制

5
9
16
4 1 E

说明

USACO 2.1

翻译来自NOCOW

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
char ansz;
int ansx,ansy,ans;
int fa[],sum[];
int get(int x,int y){
return (x-)*m+y;
}
int find(int x){
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
void add(int x,int y){
int dx=find(x),dy=find(y);
if(dx==dy) return ;
else fa[dy]=dx;
}
void work(int x,int y,int num){
int id=get(x,y);
if(num==){
if(x->=) add(id,get(x-,y));
if(x+<=n) add(id,get(x+,y));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(x+<=n) add(id,get(x+,y));
if(y->=) add(id,get(x,y-));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(x+<=n) add(id,get(x+,y));
if(x->=) add(id,get(x-,y));
if(y->=) add(id,get(x,y-)); }
else if(num==){
if(x->=) add(id,get(x-,y));
if(y->=) add(id,get(x,y-));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(x+<=n) add(id,get(x+,y));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(x+<=n) add(id,get(x+,y));
if(x->=) add(id,get(x-,y)); }
else if(num==){
if(x+<=n) add(id,get(x+,y));
if(y->=) add(id,get(x,y-)); }
else if(num==){
if(x->=) add(id,get(x-,y));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(y->=) add(id,get(x,y-));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(x->=) add(id,get(x-,y));
if(y->=) add(id,get(x,y-));
}
else if(num==){
if(x+<=n) add(id,get(x+,y));
}
else if(num==){
if(y+<=m) add(id,get(x,y+));
}
else if(num==){
if(x->=) add(id,get(x-,y));
}
else if(num==){
if(y->=) add(id,get(x,y-));
}
}
int main(){
scanf("%d%d",&m,&n);
for(int i=;i<=(n+)*(m+);i++) fa[i]=i;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
int num;scanf("%d",&num);
work(i,j,num);
}
for(int i=;i<=n*m;i++)
sum[find(i)]++;
int ans1=,ans2=;
for(int i=;i<=n*m;i++){
if(find(i)==i) ans1++;
ans2=max(ans2,sum[fa[i]]);
}
cout<<ans1<<endl<<ans2<<endl;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
if(i->=){
int x=get(i,j),y=get(i-,j);
int dx=find(x),dy=find(y);
if(dx!=dy){
if(sum[dx]+sum[dy]>ans){
ans=sum[dx]+sum[dy];
ansx=i;ansy=j;ansz='N';
}
else if(sum[dx]+sum[dy]==ans){
if(j<ansy){ ansx=i;ansy=j;ansz='N'; }
else if(j==ansy&&i>ansx){ ansx=i;ansy=j;ansz='N'; }
}
}
}
if(j->=){
int x=get(i,j),y=get(i,j-);
int dx=find(x),dy=find(y);
if(dx!=dy){
if(sum[dx]+sum[dy]>ans){
ans=sum[dx]+sum[dy];
ansx=i;ansy=j-;ansz='E';
}
else if(sum[dx]+sum[dy]==ans){
if(j-<ansy){ ansx=i;ansy=j-;ansz='E'; }
else if(j-==ansy&&i>ansx){ ansx=i;ansy=j-;ansz='E'; }
}
}
}
if(i+<=n){
int x=get(i,j),y=get(i+,j);
int dx=find(x),dy=find(y);
if(dx!=dy){
if(sum[dx]+sum[dy]>ans){
ans=sum[dx]+sum[dy];
ansx=i+;ansy=j;ansz='N';
}
else if(sum[dx]+sum[dy]==ans){
if(j<ansy){ ansx=i+;ansy=j;ansz='N'; }
else if(j==ansy&&i+>ansx){ ansx=i+;ansy=j;ansz='N'; }
}
}
}
if(j+<=m){
int x=get(i,j),y=get(i,j+);
int dx=find(x),dy=find(y);
if(dx!=dy){
if(sum[dx]+sum[dy]>ans){
ans=sum[dx]+sum[dy];
ansx=i;ansy=j;ansz='E';
}
else if(sum[dx]+sum[dy]==ans){
if(j<ansy){ ansx=i;ansy=j;ansz='E'; }
else if(j==ansy&&i>ansx){ ansx=i;ansy=j;ansz='E'; }
}
}
}
}
cout<<ans<<endl<<ansx<<" "<<ansy<<" "<<ansz;
}

74分

漏下了四面都没有墙的 也就是输入为0的。

/*用并查集处理所有情况的联通块*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
char ansz;
int ansx,ansy,ans;
int fa[],sum[];
int get(int x,int y){
return (x-)*m+y;
}
int find(int x){
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
void add(int x,int y){
int dx=find(x),dy=find(y);
if(dx==dy) return ;
else fa[dy]=dx;
}
void work(int x,int y,int num){
int id=get(x,y);
if(num==){
if(x->=) add(id,get(x-,y));
if(x+<=n) add(id,get(x+,y));
if(y+<=m) add(id,get(x,y+));
if(y->=) add(id,get(x,y-)); }
else if(num==){
if(x->=) add(id,get(x-,y));
if(x+<=n) add(id,get(x+,y));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(x+<=n) add(id,get(x+,y));
if(y->=) add(id,get(x,y-));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(x+<=n) add(id,get(x+,y));
if(x->=) add(id,get(x-,y));
if(y->=) add(id,get(x,y-)); }
else if(num==){
if(x->=) add(id,get(x-,y));
if(y->=) add(id,get(x,y-));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(x+<=n) add(id,get(x+,y));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(x+<=n) add(id,get(x+,y));
if(x->=) add(id,get(x-,y)); }
else if(num==){
if(x+<=n) add(id,get(x+,y));
if(y->=) add(id,get(x,y-)); }
else if(num==){
if(x->=) add(id,get(x-,y));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(y->=) add(id,get(x,y-));
if(y+<=m) add(id,get(x,y+)); }
else if(num==){
if(x->=) add(id,get(x-,y));
if(y->=) add(id,get(x,y-));
}
else if(num==){
if(x+<=n) add(id,get(x+,y));
}
else if(num==){
if(y+<=m) add(id,get(x,y+));
}
else if(num==){
if(x->=) add(id,get(x-,y));
}
else if(num==){
if(y->=) add(id,get(x,y-));
}
}
int main(){
freopen("testdata.in","r",stdin);
scanf("%d%d",&m,&n);
for(int i=;i<=(n+)*(m+);i++) fa[i]=i;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
int num;scanf("%d",&num);
work(i,j,num);
}
for(int i=;i<=n*m;i++)
sum[find(i)]++;
int ans1=,ans2=;
for(int i=;i<=n*m;i++){
if(find(i)==i) ans1++;
ans2=max(ans2,sum[fa[i]]);
}
cout<<ans1<<endl<<ans2<<endl;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
if(i->=){
int x=get(i,j),y=get(i-,j);
int dx=find(x),dy=find(y);
if(dx!=dy){
if(sum[dx]+sum[dy]>ans){
ans=sum[dx]+sum[dy];
ansx=i;ansy=j;ansz='N';
}
else if(sum[dx]+sum[dy]==ans){
if(j<ansy){ ansx=i;ansy=j;ansz='N'; }
else if(j==ansy&&i>ansx){ ansx=i;ansy=j;ansz='N'; }
}
}
}
if(j->=){
int x=get(i,j),y=get(i,j-);
int dx=find(x),dy=find(y);
if(dx!=dy){
if(sum[dx]+sum[dy]>ans){
ans=sum[dx]+sum[dy];
ansx=i;ansy=j-;ansz='E';
}
else if(sum[dx]+sum[dy]==ans){
if(j-<ansy){ ansx=i;ansy=j-;ansz='E'; }
else if(j-==ansy&&i>ansx){ ansx=i;ansy=j-;ansz='E'; }
}
}
}
if(i+<=n){
int x=get(i,j),y=get(i+,j);
int dx=find(x),dy=find(y);
if(dx!=dy){
if(sum[dx]+sum[dy]>ans){
ans=sum[dx]+sum[dy];
ansx=i+;ansy=j;ansz='N';
}
else if(sum[dx]+sum[dy]==ans){
if(j<ansy){ ansx=i+;ansy=j;ansz='N'; }
else if(j==ansy&&i+>ansx){ ansx=i+;ansy=j;ansz='N'; }
}
}
}
if(j+<=m){
int x=get(i,j),y=get(i,j+);
int dx=find(x),dy=find(y);
if(dx!=dy){
if(sum[dx]+sum[dy]>ans){
ans=sum[dx]+sum[dy];
ansx=i;ansy=j;ansz='E';
}
else if(sum[dx]+sum[dy]==ans){
if(j<ansy){ ansx=i;ansy=j;ansz='E'; }
else if(j==ansy&&i>ansx){ ansx=i;ansy=j;ansz='E'; }
}
}
}
}
cout<<ans<<endl<<ansx<<" "<<ansy<<" "<<ansz;
}

100分

洛谷 P1457 城堡 The Castle的更多相关文章

  1. 洛谷P1457 城堡 The Castle

    P1457 城堡 The Castle 137通过 279提交 题目提供者该用户不存在 标签USACO 难度提高+/省选- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 我们憨厚的USACO ...

  2. 洛谷 P1457 城堡 The Castle 解题报告

    P1457 城堡 The Castle 题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张"幸运爱尔兰" ...

  3. 洛谷—— P1457 城堡 The Castle

    https://www.luogu.org/problem/show?pid=1457 题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特 ...

  4. 题解 洛谷P1457 【城堡 The Castle】

    这道题,看似很烦,无从下手,但其实只要用位运算和联通快就能水过了呀. 首先,输入:似乎大意是把一个数拆成二进数的相加,分别表示\((i,j)\)东南西北是否有墙.\(1\)表示西,\(2\)表示北,\ ...

  5. P1457 城堡 The Castle

    轻度中毒 原题 :The Castle 以下为题解部分:明明辣么简单的一道题,硬是搞了1.5h,WTF?以下列出本题的一些要点. 搜索(DFS)嘛,染色嘛,统计大小嘛,很容易想,也很更易处理. 接下来 ...

  6. P1457 城堡 The Castle 位运算+BFS+思维(难题,好题)

    题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张"幸运爱尔兰"(一种彩票).结果这张彩票让他获得了这次 ...

  7. 洛谷P1263 宫廷守卫

    P1263 宫廷守卫 题目描述 从前有一个王国,这个王国的城堡是一个矩形,被分为M×N个方格.一些方格是墙,而另一些是空地.这个王国的国王在城堡里设了一些陷阱,每个陷阱占据一块空地. 一天,国王决定在 ...

  8. $loj10156/$洛谷$2016$ 战略游戏 树形$DP$

    洛谷loj Desription Bob 喜欢玩电脑游戏,特别是战略游戏.但是他经常无法找到快速玩过游戏的方法.现在他有个问题. 现在他有座古城堡,古城堡的路形成一棵树.他要在这棵树的节点上放置最少数 ...

  9. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

随机推荐

  1. 2017广东工业大学程序设计竞赛决赛 H tmk买礼物

    题意: Description 今天是校赛的日子,为了庆祝这么喜庆的日子,TMK打算买些礼物给女票LSH庆祝一下. TMK进入了雪梨超市,然后刚踏入的一瞬间,店主就对TMK说:“恭喜你成为了本店第21 ...

  2. js实现表单checkbox的单选,全选

    全选&单选 //<input type="checkbox" name="" class="quan" value=" ...

  3. Asp.Net中调用存储过程并返回输出参数

    /// <summary> /// 调用存储过程返回参数 /// </summary> /// <param name="orderId">&l ...

  4. 支持中英文和国旗的android国家代码/国际电话区号选择器

    最近在做app登录的时候,因为需要支持国外手机号注册和登录,所以就涉及到国际电话区号的选择.在github上面找了一下,国家名称基本都是只有英文版本,而手动的去把中文一个个加上实在是一件费时费力的事情 ...

  5. 乐视max2 刷入第三方recovery 然后刷入root 包 root

    乐视max2 刷入第三方recovery 然后刷入root 包 root 第三方recovery:为奇兔 刷入root 包 https://share.weiyun.com/ddcdd5ea83956 ...

  6. org.springframework.orm.hibernate4.support.OpenSessionInViewFilter

    ---恢复内容开始--- /* * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache ...

  7. python练习2 购物车程序

    # -*- coding: utf-8 -*-# @Time : 2018/10/18 16:06# @Author : Two Brother# @EMAIL : yeluyide@163.com# ...

  8. CAD参数绘制圆(网页版)

    CAD绘制图像的过程中,画圆的情况是非常常见的,用户可以设置圆的圆心位置及半径属性. 主要用到函数说明: _DMxDrawX::DrawCircle 绘制一个圆.详细说明如下: 参数 说明 DOUBL ...

  9. D. Gourmet choice并查集,拓扑结构

    D. Gourmet choice time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  10. XML和JSON

    XML XML(EXtensible Markup Language),可扩展标记语言 特点 XML与操作系统.编程语言的开发平台无关 实现不同系统之间的数据交换 作用: 数据交互 配置应用程序和网站 ...