洛谷P1331 海战 题解
题目传送门
思路
肯定食用dfs啦。。。
但关键是两条船接触了怎么判断呢??
上图:

可以发现一下规律
当两条船接触时,必有一条直线连续穿过两条船
当一条船不与另一条船接触时,没有一条直线连续穿过两条船
所以只需要在每一次碰见一条船的一部分(一条船内每个点都要拓展一遍)时,将其沿右上、左下分别拓展一遍,边拓展边用sum前缀和check一遍就好啦。。。。
核心代码:
//码风很丑,勿喷
int k=1;
while(a[i+k][j+k]==1) k++;//找到最左下的一个点(即连线段的另一个端点)
--k;//别忘了再加回来
int hh=sum[i+k][j+k]-sum[i-1][j]-sum[i][j-1]+sum[i-1][j-1];//前缀和
++k;
if(hh<k*k){//前缀和必须是k*k(一个正方形)
	puts("Bad placement.");
	return 0;//强制结束
}//沿右上
k=1;//清零
while(a[i+k][j-k]==1) ++k;//找到最左下的一个点(即连线段的另一个端点)
--k;
hh=sum[i+k][j]-sum[i-1][j]-sum[i+k][j-k-1]+sum[i-1][j-k-1];//前缀和
++k;//别忘了再加回来
if(hh<k*k){//前缀和必须是k*k(一个正方形)
	puts("Bad placement.");
	return 0;//强制结束
}//沿左下
如果没有接触的话,可以直接dfs啦。。。代码简洁:
void dfs(int x,int y){
	if(vis[x][y]==1) return ;//如果已经拓展过直接退出
	vis[x][y]=1;//标记
	if(a[x][y+1]==1) dfs(x,y+1);//向四个方向拓展,标记为此船
	if(a[x-1][y]==1) dfs(x-1,y);
	if(a[x+1][y]==1) dfs(x+1,y);
	if(a[x][y-1]==1) dfs(x,y-1);
}
所有代码:(非常“简洁”。。。)
#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int ret=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();}
	while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
	return ret*f;
}//丑陋的读优
void write(int x){
	if(x<0){
		putchar('-');
		write(-x);
		return ;
	}
	if(x<10) putchar(x+'0');
	else{
		write(x/10);
		putchar(x%10+'0');
	}
}//丑陋的输优
int n,m,a[1010][1010],sum[1010][1010];
int vis[1010][1010],ans;
void dfs(int x,int y){
	if(vis[x][y]==1) return ;
	vis[x][y]=1;
	if(a[x][y+1]==1) dfs(x,y+1);
	if(a[x-1][y]==1) dfs(x-1,y);
	if(a[x+1][y]==1) dfs(x+1,y);
	if(a[x][y-1]==1) dfs(x,y-1);
}//丑陋的dfs
int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char ch;cin>>ch;
			if(ch=='#') a[i][j]=1;
		}
	}//读入
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
		}
	}//前缀和
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]==1){
				int k=1;
				while(a[i+k][j+k]==1) k++;
				--k;
				int hh=sum[i+k][j+k]-sum[i-1][j]-sum[i][j-1]+sum[i-1][j-1];
				++k;
				if(hh<k*k){
					puts("Bad placement.");
					return 0;
				}
				k=1;
				while(a[i+k][j-k]==1) ++k;
				--k;
				hh=sum[i+k][j]-sum[i-1][j]-sum[i+k][j-k-1]+sum[i-1][j-k-1];
				++k;
				if(hh<k*k){
					puts("Bad placement.");
					return 0;
				}
			}//不想再提了。。。判断船只是否接触
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]==1&&vis[i][j]==0){
				++ans;
				dfs(i,j);
			}//dfs统计答案
		}
	}
	cout<<"There are ";
	write(ans);
	cout<<" ships.";putchar('\n');//输出
	return 0;//结束。。。。
}
/*************************
用时: 102ms / 内存: 5152KB
代码:1.63KB C++
By yuzhengxi
**************************/
												
											洛谷P1331 海战 题解的更多相关文章
- 洛谷P1331海战
		
题目描述 在峰会期间,武装部队得处于高度戒备.警察将监视每一条大街,军队将保卫建筑物,领空将布满了F-2003飞机.此外,巡洋船只和舰队将被派去保护海岸线. 不幸的是因为种种原因,国防海军部仅有很少的 ...
 - 洛谷——P1331 海战
		
P1331 海战 题目描述 在峰会期间,武装部队得处于高度戒备.警察将监视每一条大街,军队将保卫建筑物,领空将布满了F-2003飞机.此外,巡洋船只和舰队将被派去保护海岸线.不幸的是因为种种原因,国防 ...
 - 洛谷 P1331 海战
		
传送门 题解:由于船是方形的,所以比较简单.但是考试的时候跪了,orz.忘了考虑类似一圈井号中间有一摊水. 可以只考虑这个点上方和左边点的情况,这样分为四种情况.一种是左边是一滩水, ...
 - 洛谷P1331 海战
		
海战 题目链接 这还是一道联通块的题,只是需要判断是否存在以下四种情况: o. .o oo oo oo oo o. .o 如果存在就是Bad placement. 要注意标记以下,不然会出现多次输出B ...
 - 洛谷NOIp热身赛题解
		
洛谷NOIp热身赛题解 A 最大差值 简单树状数组,维护区间和.区间平方和,方差按照给的公式算就行了 #include<bits/stdc++.h> #define il inline # ...
 - 洛谷P2827 蚯蚓 题解
		
洛谷P2827 蚯蚓 题解 题目描述 本题中,我们将用符号 ⌊c⌋ 表示对 c 向下取整. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现 ...
 - 洛谷P1816 忠诚 题解
		
洛谷P1816 忠诚 题解 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人 ...
 - [POI 2008&洛谷P3467]PLA-Postering 题解(单调栈)
		
[POI 2008&洛谷P3467]PLA-Postering Description Byteburg市东边的建筑都是以旧结构形式建造的:建筑互相紧挨着,之间没有空间.它们共同形成了一条长长 ...
 - [NOI 2020 Online] 入门组T1 文具采购(洛谷 P6188)题解
		
原题传送门 题目部分:(来自于考试题面,经整理) [题目描述] 小明的班上共有 n 元班费,同学们准备使用班费集体购买 3 种物品: 1.圆规,每个 7 元. 2.笔,每支 4 元. 3.笔记本,每本 ...
 
随机推荐
- body内常用标签
			
一.标签内使用的符号 # 特殊字符 空格 > 大于 < 小于 更多特殊字符:Here 二.P标签 作用:p标签表示段落 <body> <p> 吃葡萄不吐葡萄皮 ...
 - 基于索引的MySQL优化
			
今天查看MySQL慢查询日志,查看一个四表关联的SQL操作,耗时1006s.这次也是基于基于子查询的思路,对上表进行优化.使时间复杂度降到n^2级别.但优化之后时间反而是原来的三倍多. 原SQL语句: ...
 - Java并发编程原理与实战十五:手动实现一个可重入锁
			
package com.roocon.thread.ta1; public class Sequence { private MyLock lock = new MyLock(); private ...
 - virtual Box在Centos 7上的安装
			
1.首先,我们需要在oracle官网下载virtual Box的centos7版本: 下载地址为:http://download.virtualbox.org/virtualbox/5.0.12/Vi ...
 - 【leetcode 简单】 第一百四十六题 最长和谐子序列
			
和谐数组是指一个数组里元素的最大值和最小值之间的差别正好是1. 现在,给定一个整数数组,你需要在所有可能的子序列中找到最长的和谐子序列的长度. 示例 1: 输入: [1,3,2,2,5,2,3,7] ...
 - UNIX网络编程 第8章 基本UDP套接字编程
			
UDP是无连接的,不需要accept,TCP通过accept API来接受连接,并且将连接客户端的信息写入到accept将返回的新socket中,该新socket中有服务端和客户端的IP地址和端口,因 ...
 - 翻译:CommonJS的wiki
			
CommonJS的wiki资料原文 Modules/AsynchronousDefinition 异步定义的模块(国内一般叫AMD模块定义) STATUS: PROPOSAL 现状:提案 Implem ...
 - python 面试题2
			
问题一:以下的代码的输出将是什么? 说出你的答案并解释. class Parent(object): x = 1 class Child1(Parent): pass class Child2(Par ...
 - 使用mysql的SUBSTRING_INDEX函数解决项目中编码非重复问题的实现方案!
			
一 SUBSTRING_INDEX函数介绍 作用:按关键字截取字符串 substring_index(str,delim,count) 说明:substring_index(被截取字段,关键字,关键字 ...
 - ubuntu 18.04 安装 flash
			
下载源码包, 解压 sudo cp Downloads/flash_player_npapi_linux.x86_64/libflashplayer.so /usr/lib/mozilla/plugi ...