洛谷P1457 城堡(The Castle)
2015-10-10 10:14
302 查看
洛谷1457 城堡
本题地址: http://www.luogu.org/problem/show?pid=1457
题目描述
我们憨厚的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
【思路】
Dfs。
观察题目:利用位运算能够构造wall[][][]。
首先用dfs求出连通块,对每一格上色并用cnt记录颜色数目即房间大小。
其次从南到北从东向西枚举格子,如果可以则尝试拆除北墙、东墙,找到最优拆除。
【代码】
本题地址: http://www.luogu.org/problem/show?pid=1457
题目描述
我们憨厚的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
【思路】
Dfs。
观察题目:利用位运算能够构造wall[][][]。
首先用dfs求出连通块,对每一格上色并用cnt记录颜色数目即房间大小。
其次从南到北从东向西枚举格子,如果可以则尝试拆除北墙、东墙,找到最优拆除。
【代码】
#include<iostream> #include<cstring> #define FOR(a,b,c) for(int a=(b);a<=(c);a++) using namespace std; const int maxn = 100; const int dx[]={0,-1,0,1}; const int dy[]={-1,0,1,0}; int wall[maxn][maxn][4]; int c[maxn][maxn],colors,cnt[maxn*maxn]; int n,m; inline bool inside(int x,int y) { return x>=1 && x<=n && y>=1 && y<=m; } void dfs(int x,int y) { for(int i=0;i<4;i++) if(!wall[x][y][i]) { int xx=x+dx[i] , yy=y+dy[i]; if(inside(xx,yy) && !c[xx][yy]) { c[xx][yy]=colors; cnt[colors]++; dfs(xx,yy); } } } int main() { ios::sync_with_stdio(false); cin>>m>>n; int G; FOR(i,1,n) FOR(j,1,m) { cin>>G; for(int k=0;k<4;k++) if(G&(1<<k)) wall[i][j][k]=1; } int max_s=0; FOR(i,1,n) FOR(j,1,m) { if(c[i][j]) continue; ++colors; c[i][j]=colors; cnt[colors]++; dfs(i,j); max_s=max(max_s,cnt[colors]); } cout<<colors<<"\n"<<max_s<<"\n"; char op; int ans_x,ans_y,ans=0; FOR(j,1,m) for(int i=n;i;i--) { if(i>1 && wall[i][j][1] && c[i][j]!=c[i-1][j]) { if(cnt[c[i-1][j]]+cnt[c[i][j]]>ans) { ans=cnt[c[i-1][j]]+cnt[c[i][j]]; ans_x=i , ans_y=j , op='N'; } } if(j<m && wall[i][j][2] && c[i][j]!=c[i][j+1]) { if(cnt[c[i][j+1]]+cnt[c[i][j]]>ans) { ans=cnt[c[i][j+1]]+cnt[c[i][j]]; ans_x=i , ans_y=j , op='E'; } } } cout<<ans<<"\n"<<ans_x<<" "<<ans_y<<" "<<op; return 0; }
相关文章推荐
- linux 软连接方式实现上传文件存储目录的无缝迁移
- TCP 算法总结
- C#将dll打包到程序中
- static变量在结构化设计和面向对象设计方面的总结
- dhtmlx技术使用总结与介绍中文手册
- HttpClient 教程 (一)
- iOS9新系统下App Store应用上传新指南
- linux 软连接方式实现上传文件存储目录的无缝迁移
- 安卓-属性动画
- 开始写点东西
- 常用的git命令
- Hibernate的乐观锁与悲观锁
- c语言和java的区别
- JavaScript获取屏幕、浏览器、网页高度宽度
- samba技术留档
- 滴滴拿牌照:解读专车“上海模式”的四大要点
- Activity和Fragment之间的传值
- 学习C++要点
- Zip操作的工具类
- MongoDB 性能优化五个简单步骤