【补题及学习2】


这周末连打三场(lanqiao、C4模拟、ICPC校赛),真赶

题1

岛屿个数

问题描述

小蓝得到了一副大小为 M×N 的格子地图,可以将其视作一个只包含字符 ‘0’(代表海水)和 ‘1’(代表陆地)的二维数组,地图之外可以视作全部是海水,每个岛屿由在上/下/左/右四个方向上相邻的 ‘1’ 相连接而形成。
在岛屿 A 所占据的格子中,如果可以从中选出 k 个不同的格子,使得他们的坐标能够组成一个这样的排列:(x0,y0),(x1,y1),…,(xk−1,yk−1),其中 (xi+1modk,yi+1modk)是由 (xi,yi) 通过上/下/左/右移动一次得来的 (0≤i≤k−1),此时这 k 个格子就构成了一个“环”。如果另一个岛屿 B 所占据的格子全部位于这个“环”内部,此时我们将岛屿 B 视作是岛屿 A的子岛屿。若 B是 A的子岛屿,C 又是 B 的子岛屿,那 C也是 A的子岛屿。
请问这个地图上共有多少个岛屿?在进行统计时不需要统计子岛屿的数目。

输入格式

第一行一个整数 T,表示有 T组测试数据。
接下来输入 T 组数据。对于每组数据,第一行包含两个用空格分隔的整数 M、N表示地图大小;接下来输入 M 行,每行包含 N 个字符,字符只可能是 ‘0’ 或 ‘1’。

输出格式

对于每组数据,输出一行,包含一个整数表示答案。

样例输入

2
5 5
01111
11001
10101
10001
11111
5 6
111111
100001
010101
100001
111111

样例输出

1
3

样例说明

对于第一组数据,包含两个岛屿,下面用不同的数字进行了区分:

01111
11001
10201
10001
11111

岛屿 2 在岛屿 1的“环”内部,所以岛屿 2 是岛屿 1 的子岛屿,答案为 1。
对于第二组数据,包含三个岛屿,下面用不同的数字进行了区分:

111111
100001
020301
100001
111111

注意岛屿 3 并不是岛屿 1或者岛屿 2 的子岛屿,因为岛屿 1 和岛屿 2 中均没有“环”。

评测用例规模与约定

对于 30 的评测用例,1≤M,N≤10。
对于 100 的评测用例,1≤T≤10,1≤M,N≤50。

解题

说起来我看考点是bfs但却是用了dfs做题

初始

预留边缘,在先沿边缘八方向搜索外海,从相邻寻找最外层岛。

import os
import sys
f=(0,1),(1,0),(0,-1),(-1,0),(1,1),(1,-1),(-1,-1),(-1,1)
def dfs(u,s,sq):
  sq[u[0]][u[1]]=9-s
  for dx,dy in f[:8-s*4]:
    x,y=u[0]+dx,u[1]+dy
    if sq[x][y]==s:
      dfs((x,y),s,sq)
# 请在此输入您的代码
T=int(input())
for t in range(T):
  M,N=map(int,input().split())
  sq=[[2]*(N+2)]+[list(map(int,'2'+input()+'2'))for j in range(M)]+[[2]*(N+2)]
  c=0
  for i in range(1,1+M):
    if sq[i][1]==0:
      dfs((i,1),0,sq)
    if sq[i][N]==0:
      dfs((i,N),0,sq)
  for j in range(1,1+N):
    if sq[1][j]==0:
      dfs((1,j),0,sq)
    if sq[M][j]==0:
      dfs((M,j),0,sq)
  for i in range(1,1+M):
    for j in range(1,1+N):
      if sq[i][j]==1:
        for dx,dy in f[:4]:
          x,y=i+dx,j+dy
          if sq[x][y]==9:
            c+=1
            dfs((i,j),1,sq)
            break
  print(c)

集成

把搜索岛的过程集成在搜索外海之中

import os
import sys
f=(0,1),(1,0),(0,-1),(-1,0),(1,1),(1,-1),(-1,-1),(-1,1)
def dfs(u,s,sq):
  sq[u[0]][u[1]]=9-s
  for dx,dy in f[:8-s*4]:
    x,y=u[0]+dx,u[1]+dy
    if sq[x][y]==s:
      dfs((x,y),s,sq)
    elif sq[x][y]==1:
      global c
      c+=1
      dfs((x,y),1,sq)
# 请在此输入您的代码
T=int(input())
for t in range(T):
  M,N=map(int,input().split())
  sq=[[2]*(N+2)]+[list(map(int,'2'+input()+'2'))for j in range(M)]+[[2]*(N+2)]
  c=0
  for i in range(1,1+M):
    if sq[i][1]==0:
      dfs((i,1),0,sq)
    if sq[i][N]==0:
      dfs((i,N),0,sq)
  for j in range(1,1+N):
    if sq[1][j]==0:
      dfs((1,j),0,sq)
    if sq[M][j]==0:
      dfs((M,j),0,sq)
  '''for i in range(1,1+M):
    for j in range(1,1+N):
      if sq[i][j]==1:
        for dx,dy in f[:4]:
          x,y=i+dx,j+dy
          if sq[x][y]==9:
            c+=1
            dfs((i,j),1,sq)
            break'''
  print(c)

题2

tee边形
与队友练习校赛时选的题目之一

题目描述

tee是一种可爱的生物,生活在teeworld。你知道tee是什么吗,你知道tee的生活条件有多艰难吗,你不知道,你不关心,你只关心今天吃什么外卖

王tee看着手上的玩具又双叒叕陷入了沉思,“为什么我的玩具是一个正n边形,好怪哦”,他看着毒辣辣的太阳,将玩具举起来,迷着眼睛,“真是一个完美的图案…”
如果有一个圆O,和圆上的一点P,可知存在唯一的正k边形,满足以下条件:
1. 正k边形顶点中的某一点为P
2. 正k边形的外接圆为O

请求出正k边形上从P点顺时针数的第m个顶点的坐标(不包括点p)

输入描述:

第一行给定一个正整数T(1≤T≤105),表示数据组数。
接下来每一组数据:
第一行给定两个实数X,Y(∣X∣,∣Y∣≤109),表示圆心坐标。
第二行给定两个实数X1,Y1(∣X1∣,∣Y1∣≤109),表示点P的坐标,且满足P在圆O上。
第三行给定两个正整数k,m(3≤k≤106,1≤m<k)。

输出描述:

对每一组数据,输出一行两个数X,Y,表示正k边形上从P点顺时针数的第m个顶点的坐标(不包括P)的x,y坐标。
如果您的答案的绝对误差或相对误差不超过 10−4 ,则认为您的答案是正确的。即你的答案X,Y和目标答案X′,Y′之间需要满足∣X−X′∣/max⁡(1,∣X′∣)≤10-4且∣Y−Y′∣/max⁡(1,∣Y′∣)≤10-4才被认为是正确答案

示例1

输入

2
3 3
1 1
4 2
3 4.4641016151378
7 4.4641016151378
6 4

输出

5 5
1 7.9282032302756

说明

图一第一幅图,A点顺时针第二个为点D
第一幅图,A点顺时针第二个为点D
图2
第二幅图,D点顺时针第四个为点F

备注:

如果你们做不出来,王tee会伤心的

解题

纯数学

Py组

from math import*
T=int(input())
for i in range(T):
    X_,Y_=map(float,input().split())
    X0,Y0=map(float,input().split())
    k,m=map(int,input().split())
    DX,DY=X0-X_,Y0-Y_
    p=hypot(DX,DY)
    s1,s2=atan2(DY,DX),2*pi*m/k
    s=s1-s2
    dx,dy=p*cos(s),p*sin(s)
    x,y=X_+dx,Y_+dy
    print(x,y)

C组

注意编译器版本

//#include<bits/stdc++.h>
#include<stdio.h>
#include<math.h>
//float hypot(double x,double y){retutn sqrt(x*x+y*y);}
int main()
{
	int T,k,m;
	double X_,Y_,X0,Y0,x,y;
	double DX,DY,p,s1,s2,s,dx,dy;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%lf%lf",&X_,&Y_);
		scanf("%lf%lf",&X0,&Y0);
		scanf("%d%d",&k,&m);
		DX=X0-X_;DY=Y0-Y_;
		p=hypot(DX,DY);
		s1=atan2(DY,DX);s2=2*M_PI*m/k;
		s=s1-s2;
		dx=p*cos(s);dy=p*sin(s);
		x=X_+dx;y=Y_+dy;
		printf("%lf %lf\n",x,y);
	}
	return 0;
}

语法

math

在C中也是封装了π等值,hypot欧几里得范数,atan2据坐标反正切

STLqueue

虽然在算竟中我们常使用万能头,但在本地编译器中可能出错,所以这里还是标注所属,不过deque倒是好分辨。

#include<deque>
pair<T1>q{};
q.push(q.front()),p.pop();
!q.empty(),q.size(),q.back()

下周笔记写校赛题吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值