音视频基础知识

news/2024/10/23 8:38:26/

视频基础知识

分辨率

分辨率又称为解析度,分辨率越高,像素越多,图像越清晰。

视频分辨率:又称为图像分辨率,由视频的宽高组成,表示形式宽x高,常见的视频分辨率有480P、720P、1080P、2K(2048x1080/2160x1440)、4K(4096x2160/3840x2160)

帧率

视频帧率:

测量显示帧数的量度,单位为每秒显示帧数(FPS,全称为Frame Per Second)。一般视频帧率为24fps,P制(PAL,德国提出,中国、印度、巴基斯坦等国家使用)为25fps,也就是每帧显示40ms,N制(NTSC,美国标准委员会提出,美国、日本、韩国等国家使用)为30fps。有些超高帧率的视频达到60fps。

显示帧率:

以帧为单位的位图图像连续出现在显示器的频率,也称为刷新速率。Android设备刷新率一般为60Hz,也就是帧率为60fps,每帧为16ms,超过16ms能给人的肉眼带来延迟卡顿的感觉。做性能优化方面,也就是保证从测量、布局、绘制、上传指令、与GPU交换缓冲区等一系列动作在16ms完成。Android11支持120Hz的更高帧率,一般为对帧率要求极高的应用场景,比如互动游戏。

像素格式

目前广泛使用的有两种:

RGB

RGB即红绿蓝三个通道的颜色模型,每个像素由三个颜色通道的取值组成,代表了像素的红、绿、蓝三个基本颜色成分的浓度,RGB模式下每个像素需要占用三个字节的存储空间,而且强调颜色分量之间的独立性,对于色调、亮度、色彩鲜艳、清晰度要求高的场合使用比较多,如显示器、电视、摄像机等。

  • R:Red——红色分量;
  • G:Green——绿色分量;
  • B:Blue——蓝色分量;

对于RGB格式,每个像素通常由3个8位(即24位)的分量组成,即红(R)、绿(G)和蓝(B)三原色。因此,对于RGB格式,每个像素通常占用3个字节。

YUV

YUV则是一种基于亮度和色差的颜色编码方式,采用亮度(Y)和两个色差(U、V)分量来表示色彩信息。其中,亮度(Y)代表黑白灰调,色差(U、V)代表绿色和蓝色相对于红色的偏差。YUV模式下,色彩分量被分开表示,人眼感知亮度和颜色不同,YUV模式将图像的亮度和颜色分开处理,不仅可以节省存储空间,而且适合人眼的视觉特性,优化了图像的压缩,常用于数字电视、DVD、视频编码等应用中。

对于YUV格式,每个像素通常由1个亮度分量(即Y)和2个色度分量(即U和V)组成。通常为了保证兼容性和采样精度,YUV格式通常进行压缩。对于4:2:0压缩方式的YUV,每4个像素共用2个UV分量,因此每个像素由1.5个分量组成。因此,对于YUV 4:2:0格式,每个像素通常占用1.5个字节。

  • Y(亮度):表示灰度,即白到黑的程度,取值范围为0~255。
  • U(色度):表示从洋红到青色的程度,取值范围为-128~127。
  • V(色度):表示从黄色到蓝色的程度,取值范围为-128~127。

综合来说,RGB模式适用于图像的处理与操作,而YUV模式则适用于视频的压缩与编码

YUV 是一种将颜色和亮度分离的色彩编码系统,它将图像中的亮度(明度)信息与颜色信息(色度)分开进行编码。在许多视频编解码算法(如 H.264)中,采用 YUV 格式进行数据传输和处理,因为与 RGB 相比,YUV 优势在于更加节省带宽和存储空间。

然而,由于计算机处理图像的方式主要是基于 RGB 色彩空间,所以需要将 YUV 转换为 RGB 才能在计算机上进行处理和显示。

码流率

码流(Bit Rate)是指视频文件在单位时间内使用的数据流量,也叫码率或码流率,通俗一点的理解就是取样率,是视频编码中画面质量控制中最重要的部分,一般我们用的单位是kb/s或者Mb/s。一般来说同样分辨率下,视频文件的码流越大,压缩比就越小,画面质量就越高。码流越大,说明单位时间内取样率越大,数据流,精度就越高,处理出来的文件就越接近原始文件,图像质量越好,画质越清晰,要求播放设备的解码能力也越高。

如何根据图片分辨率算码流大小?

例如:我们以1920x1080分辨率计算,图片格式为YUV420,帧率为30 FPS,那么码流大小为:19201080(3/2)830/(1024*1024) = 89 Mb/s,至于为什么乘以3/2那就和YUV420格式存储有关系了,乘8即将Byte转为bit,如果图片格式为RGB24即一帧图片大小为分辨率x3,如果是RGB32即一帧图片大小为分辨率x4。

音频基础知识

采样率

对声音信号每秒的采样次数,采样率越高,声音的还原越真实。采样率单位为Hz,常见的采样率有:8000Hz、16000Hz、44100Hz、48000Hz。人类一般能够听到的声音范围:20Hz~20000Hz。根据奈奎斯特采样定理:当采样频率大于信号中最高频率的2倍时,采样后的数字信号能够完整保留原始信号的信息。

声道

指声音在录制或播放时,在不同空间位置采集或回放的相互独立音频信号。声道数指在录音时的音源数量,或者在播放时的扬声器数量。

声道布局

不同声道数对应不同声道布局。常见的声道布局有单声道(mono)、立体声道(stereo)、四声环绕、5.1声道。

  • 单声道:只有一个声道,优点数据量小,amr_nb和amr_wb默认为单声道,缺点是缺乏对声音位置定位。
  • 立体声道:一般为两个声道,由左声道、右声道组成,改善对声音位置定位的状况。
  • 四声环绕:由前左、前右、后左、后右组成,形成立体环绕。4.1声道是在四声环绕基础上,增加一个低音。
  • 5.1声道:在4.1基础上,增加一个中场声道,杜比AC3就是采用5.1声道,也就是影院宣传的杜比音效。

音质

  • 音质:声音的质量,经过编码压缩后的音频信号保真度,由音量、音高和音色组成。
  • 音量:音频的强度,数值范围0-100,静音时为0,最大值为100。Android中有提供音量增强LoudnessEnhancer,调节声音分贝值。
  • 音高:声音的音调,即音频频率或每秒变化次数。
  • 音色:音频泛音,又称为音品,不同声音表现在波形方面与众不同的特性。

视频播放器原理

视频播放一般经过一下几个步骤:

  1. 协议解析(本地文件不需要)
  2. 解封装
  3. 音视频解码
  4. 音视频同步

暂时无法在Lark文档外展示此内容

下面就围绕着这些操作步骤来了解里面的内容:

流媒体协议

流媒体协议是服务器与客户端之间通信遵循的规定。当前网络上主要的流媒体协议如表所示。

名称传输层协议使用领域
HTTPTCP点播
RTMPTCP直播
SRTUDP直播
HLSTCP直播+点播
QUICUDP直播
RTSP+RTPTCP+UDPIPTV
RTMFPUDP直播
MMSTCP+UDP直播+点播

目前使用比较多的协议:

HTTP

HTTP是Hypertext Transfer Protocol(超文本传输协议)的缩写,是一种应用层协议,常用于网页数据传输。在视频直播和点播中,HTTP作为一种流媒体传输协议也受到了广泛的应用,例如HLS、DASH等协议都是基于HTTP的。HTTP协议的优点是通用性强,可以通过标准的web服务器进行传输,且具有自适应码率等特性。缺点是延迟较高,不适合实时性要求高的应用场景。并且HTTP协议下,每次请求都需要重新建立TCP连接,导致资源浪费。

RTMP

RTMP是Real-Time Messaging Protocol(实时消息传输协议)的缩写,是Adobe公司开发的一种流媒体传输协议。常用于实时视频直播和点播等场景。与HTTP协议相比,RTMP具有更低的延迟和更高的稳定性。但是,RTMP需要特定的流媒体服务器来支持,相对来说不够灵活且成本较高。

SRT

SRT是Secure Reliable Transport(安全可靠传输)的缩写,是一种新兴的协议,能够提供低延迟和高可靠性的视频传输。SRT使用UDP协议传输数据,同时添加了错误纠正、加密等功能。相比较RTMP和HTTP,SRT协议传输延迟更低且更加稳定,且能够支持穿越NAT等复杂网络环境。但是,SRT属于新兴的技术,目前的应用范围较为有限。

HLS

HLS是http live streaming是由Apple公司定义的基于http的流媒体实时传输协议,可实现流媒体的直播和点播,主要用于ios系统。

原理是将整个流分为多个小的文件来下载,每次只下载一个。客户端只要不停的按顺序播放从服务器获取到的文件,就实现了直播。

分段推送的特点,决定了HLS的延迟一般会高于普通的流媒体直播协议。

主要场景就是使用TS文件索引组成M3U8文件进行播放。

QUIC

QUIC是基于UDP的一种传输协议,最初由Google开发。QUIC具有低延迟、高速率、高安全性等特点,支持快速握手和零RTT建立连接。QUIC协议还支持多路复用,能够实现流媒体传输的逐片下载,提供更好的视频传输质量。目前,QUIC正在逐渐被各大浏览器和网站所采用。

bilibili直播使用的就是RTMP和SRT

综合来说就是直播场景使用RTMP、SRT、HLS,点播场景使用HTTP、QUIC、HLS

封装格式

封装格式的主要作用是把视频码流和音频码流按照一定的格式存储在一个文件中。也就是我们常见的视频文件后缀名。

常见的封装格式:

名称支持的视频编码支持的音频编码
MP4MPEG-2, MPEG-4, H.265,H.264, H.263等AAC, MPEG-1 Layers I, II, III, AC-3等
TSMPEG-1, MPEG-2, MPEG-4, H.264MPEG-1 Layers I, II, III, AAC
MOVMPEG-4, H.264,ProRes,SorensonMP3, ADPCM, Linear PCM, AAC等
MKV几乎所有格式几乎所有格式
FLVSorenson, VP6, H.264MP3, ADPCM, Linear PCM, AAC等
AVI几乎所有格式几乎所有格式

MP4

MP4(MPEG-4 Part 14)是一种先进的数字音视频封装格式,以其跨平台、流行和可扩展性而闻名。MP4支持多种编解码器、多个音轨和多个字幕轨道,可以在各种硬件和软件平台上实现兼容性。

TS

TS文件(.ts)是一种常用的MPEG-2视频封装格式,主要用于传输数字电视信号或存储DVD文件,采用了MPEG-2 TS标准,该格式支持多种编解码器、多个音轨和字幕,具有高效的传输性能,并能够在网络传输中很好的处理丢包、错误等问题。

AVI

AVI(Audio Video Interleave)是一种老旧的Microsoft开发的音视频文件封装格式,支持多种编解码器和字幕,然而在实际应用中,不支持流媒体,AVI的兼容性和可应用范围性都受到很大的限制,已经渐渐被新的视频文件封装格式替代。

MOV

MOV是苹果公司开发的一种常用的音视频文件封装格式,该格式包含多种编解码器、字幕等源素材信息。MOV的兼容性很好,在不同的操作系统和设备上都能够被流畅播放。

MKV

Matroska Video File,即MKV格式,是一种开源、免费、高质量的音视频文件封装格式。MKV格式支持多种编解码器、多个音轨和多个字幕轨道,同时支持高比特率、高清晰度的视频文件。

FLV

FLV是Flash视频的缩写,是一种带有字幕和互动元素的视频文件格式,支持实时流媒体传输,在互联网上被广泛应用。FLV格式在播放方面兼容性强,支持流式播放和快进等基本操作。

视频编码

为什么需要对视频编码

对于视频数据而言,视频编码的最主要目的是数据压缩。这是因为动态图像的像素形式表示数据量极为巨大,存储空间和传输带宽完全无法满足保存和传输的需求。例如,图像的每个像素的三个颜色分量RGB各需要一个字节表示,那么每一个像素至少需要3字节,分辨率1280×720的图像的大小为2.76M字节。

如果对于同样分辨率的视频,如果帧率为25帧/秒,那么传输所需的码率将达到553Mb/s!如果对于更高清的视频,如1080P、4k、8k视频,其传输码率更是惊人。这样的数据量,无论是存储还是传输都无法承受。因此,对视频数据进行压缩称为了必然之选。

视频信息为什么可以被压缩

视频信息之所以存在大量可以被压缩的空间,是因为其中本身就存在大量的数据冗余。其主要类型有:

  1. 时间冗余:视频相邻的两帧之间内容相似,存在运动关系
  2. 空间冗余:视频的某一帧内部的相邻像素存在相似性
  3. 编码冗余:视频中不同数据出现的概率不同
  4. 视觉冗余:观众的视觉系统对视频中不同的部分敏感度不同

针对这些不同类型的冗余信息,在各种视频编码的标准算法中都有不同的技术专门应对,以通过不同的角度提高压缩的比率。

视频编码标准

目前使用比较多的视频编码标准就是

H.264/AVC

H.265/HEVC

两者对比

  1. 压缩比:H.265相对于H.264可以提供更高的压缩比,即在同样视频质量下,H.265视频文件的大小会更小,更节省存储空间。
  2. 视频质量:H.265相对于H.264同样画面质量下能够更低码率来达到视频的传输和存储,因此H.265在视频质量方面也略优于H.264。
  3. 存储空间:由于H.265压缩比更高,可以在同样的存储空间下存储更多的视频文件。
  4. 性能要求:由于H.265的算法更加复杂,对硬件的性能要求更高,需要更高级的处理器和显卡才能达到较高的实时编码和解码速度。

综上所述,H.265相比于H.264具有更高的压缩比和更好的视频质量,但需要更高的性能要求。

开源实现:

H.264 : openh264、x264

H.265 : libde265、x265、vp9

音频编码

使用音频压缩技术的原因

要算一个PCM音频流的码率是一件很轻松的事情,采样率值×采样大小值×声道数 bps。一个采样率为44.1KHz,采样大小为16bit,双声道的PCM编码的WAV文件,它的数据速率则为 44.1K×16×2 =1411.2 Kbps。我们常说128K的MP3,对应的WAV的参数,就是这个1411.2 Kbps,这个参数也被称为数据带宽,它和ADSL中的带宽是一个概念。将码率除以8,就可以得到这个WAV的数据速率,即176.4KB/s。这表示存储一秒钟采样率为44.1KHz,采样大小为16bit,双声道的PCM编码的音频信号,需要176.4KB的空间,1分钟则约为10.34M,这对大部分用户是不可接受的,尤其是喜欢在电脑上听音乐的朋友,要降低磁盘占用,只有2种方法,降低采样指标或者压缩。降低指标是不可取的,因此有了各种压缩方案。

常见的音频编码

MP3

目前最为流行的音频编码格式之一,具有较高的压缩比和音质,但是相对较为复杂,需要较高的处理算力。此外,MP3 是有损压缩格式,可能会损失一部分音频质量。

AAC

AAC具有更好的压缩比和音质。AAC 格式相对比 MP3 更为复杂一些,需要更高的处理算力,但是由于更为高效,目前已经被广泛应用于音频编码领域。

WAV

WAV 是一种无压缩音频文件格式,音质非常好,播放时不存在数据损失,文件体积较大。WAV 适用于对音质要求非常高的场景,例如录音录音棚。

实例解析

音频信息解析:

{"streams": [{// 当前流的索引信息,对应于AVStream->index"index": 0,// 编码格式名称"codec_name": "h264",// 编码格式详细描述,这里不知道为啥没显示出来,一般为 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"codec_long_name": "unknown",// 一个编码参数"profile": "100",// TODO codec 类型"codec_type": "video",// codec tag 字符串"codec_tag_string": "avc1",// codec tag 字符串16进制方式存储"codec_tag": "0x31637661",// 视频宽度"width": 1280,// 视频高度"height": 720,// 编码视频的宽 编解码时对齐的数据,显示时不用"coded_width": 1280,// 编码视频的高"coded_height": 720,"closed_captions": 0,"film_grain": 0,// TODO IPB帧排列时,两个P之间有多少个B帧,为0表示没有B帧"has_b_frames": 0,// TODO 像素点格式"pix_fmt": "yuv420p",// 与profile一起出现,对应d的时参考标准中有对应的参数描述"level": 52,// 调色参数 Start"color_range": "tv","color_space": "smpte170m","color_transfer": "smpte170m","color_primaries": "bt470bg",// 调色参数 End"chroma_location": "left","field_order": "progressive","refs": 1,"is_avc": "true","nal_length_size": "4","id": "0x1",// 实际帧率"r_frame_rate": "30/1",// 平均帧率"avg_frame_rate": "994000/33133",// 时间基,通常和帧率有对应关系"time_base": "1/90000",// 开始时间戳"start_pts": 0,// 开始时间 s"start_time": "0.000000",// 时长时间戳"duration_ts": 2981970,// 时长 s"duration": "33.133000",// TODO 码率"bit_rate": "2484458",// TODO 原始数据每个采样展位"bits_per_raw_sample": "8",// 总帧数"nb_frames": "994","extradata_size": 34,"disposition": {"default": 1,"dub": 0,"original": 0,"comment": 0,"lyrics": 0,"karaoke": 0,"forced": 0,"hearing_impaired": 0,"visual_impaired": 0,"clean_effects": 0,"attached_pic": 0,"timed_thumbnails": 0,"captions": 0,"descriptions": 0,"metadata": 0,"dependent": 0,"still_image": 0},"tags": {"language": "und","handler_name": "VideoHandler","vendor_id": "[0][0][0][0]"}},{"index": 1,"codec_name": "aac","codec_long_name": "unknown","profile": "1","codec_type": "audio","codec_tag_string": "mp4a","codec_tag": "0x6134706d","sample_fmt": "fltp","sample_rate": "44100","channels": 1,"channel_layout": "mono","bits_per_sample": 0,"id": "0x2","r_frame_rate": "0/0","avg_frame_rate": "0/0","time_base": "1/44100","start_pts": 0,"start_time": "0.000000","duration_ts": 1458178,"duration": "33.065261","bit_rate": "47932","nb_frames": "1422","extradata_size": 2,"disposition": {"default": 1,"dub": 0,"original": 0,"comment": 0,"lyrics": 0,"karaoke": 0,"forced": 0,"hearing_impaired": 0,"visual_impaired": 0,"clean_effects": 0,"attached_pic": 0,"timed_thumbnails": 0,"captions": 0,"descriptions": 0,"metadata": 0,"dependent": 0,"still_image": 0},"tags": {"language": "und","handler_name": "SoundHandler","vendor_id": "[0][0][0][0]"}}],"chapters": [],"format": {// 视频名称"filename": "/data/user/0/com.hsw.ffmpegkitdemo/files/private.mp4",// 容器中流的个数:视频流、音频流。// 多个视频流可能是因为不同分辨率的版本、色彩等。不同的音频流可能是不同的音轨、多语言"nb_streams": 2,// 代表文件的程序数// 个人认为当为多个场景应该是抖音PK、SWITCH中的两人分屏操作游戏。多个程序来控制的。"nb_programs": 0,// 文件的容器格式的名称,// 它的扩展名可以其中的任意一个,这些格式的作用就是表示这个文件可以在支持这些格式的播放器上进行播放,所以该文件可以在多种播放器上进行播放"format_name": "mov,mp4,m4a,3gp,3g2,mj2",// 开始时间"start_time": "0.000000",// 时长单位为s"duration": "33.133000",// 文件的大小 单位bit"size": "10518629",// todo 码率 单位 bit/s"bit_rate": "2539734",// 表示输入文件格式检测的程度的值,0-100 值越高格式越确定// 它有助于确保即使文件扩展名与实际文件格式不匹配时,仍选择最合适的格式。"probe_score": 100,"tags": {// 代表一种标识视频文件的主要格式的字符串,// 这个字符串通常是一种四字符的代码,它表示“最好”基于哪种格式来解析当前的文件。// 例如: MOV:QuickTime/MOV,ISOM:MP4格式"major_brand": "isom",// 表示该视频文件的格式的次要版本//这个信息对于确定视频文件是否支持某些功能或编解码器非常重要。例如,如果该文件的格式是一个老版本,那么它可能不支持某些功能或有关解码的限制,而如果该文件的格式是最新版本,那么它可能支持更多的功能和更高的质量"minor_version": "512",// 在 MP4 文件中的一个转换类型字符串,它标识 MP4 文件兼容的品牌或格式"compatible_brands": "isomiso2avc1mp41",// Lavf表示的是FF mpeg输出的文件,后面的编号代表了FF mpeg的版本代号,"encoder": "Lavf58.20.100"}}
}

音频信息解析

{"streams": [{"index": 0,"codec_name": "aac","codec_long_name": "unknown","profile": "1","codec_type": "audio","codec_tag_string": "mp4a","codec_tag": "0x6134706d","sample_fmt": "fltp","sample_rate": "44100","channels": 2,"channel_layout": "stereo","bits_per_sample": 0,"id": "0x1","r_frame_rate": "0/0","avg_frame_rate": "0/0","time_base": "1/44100","start_pts": 2624,"start_time": "0.059501","duration_ts": 9902080,"duration": "224.536961","bit_rate": "95397","nb_frames": "9670","extradata_size": 5,"disposition": {"default": 1,"dub": 0,"original": 0,"comment": 0,"lyrics": 0,"karaoke": 0,"forced": 0,"hearing_impaired": 0,"visual_impaired": 0,"clean_effects": 0,"attached_pic": 0,"timed_thumbnails": 0,"captions": 0,"descriptions": 0,"metadata": 0,"dependent": 0,"still_image": 0},"tags": {"creation_time": "2023-01-03T06:53:32.000000Z","language": "und","handler_name": "Sound Media Handler","vendor_id": "[0][0][0][0]"}}],"chapters": [{"id": 0,"time_base": "1/10000000","start": 595011,"start_time": "0.059501","end": 2245964570,"end_time": "224.596457","tags": {"title": "日日 (Days)"}}],"format": {"filename": "/data/user/0/com.hsw.ffmpegkitdemo/files/wind.mp3","nb_streams": 1,"nb_programs": 0,"format_name": "mov,mp4,m4a,3gp,3g2,mj2","start_time": "0.059501","duration": "224.536956","size": "2720189","bit_rate": "96917","probe_score": 100,// 当把本地歌曲倒入到网易云音乐中,它会自动匹配上对应的歌手、专辑、名称。 应该就是从这里获取的// 凭借获取的信息再去数据库中去匹配对应的歌词"tags": {"major_brand": "mp42","minor_version": "0","compatible_brands": "M4A mp42isom","creation_time": "2023-01-03T06:53:32.000000Z",// 专辑"album": "日日 (Days)",// 歌手"artist": "陈粒","iTunSMPB": " 00000000 00000A40 0000003E 0000000000970D82 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000",// 歌曲名称"title": "日日 (Days)","encoder": "Nero AAC codec / 1.5.4.0"}}
}

http://www.ppmy.cn/news/118966.html

相关文章

Python高光谱遥感数据处理与机器学习教程

详情点击链接:Python高光谱遥感数据处理与机器学习 一,高光谱 1.高光谱遥感 二,高光谱传感器与数据获取 1.高光谱传感器类型 2.高光谱数据获取 三,高光谱数据预处理 1.高光谱图像 2.辐射定标 3.大气校正 4.光谱平滑和重采…

麓言信息学UI设计4大雷区,你踩了几个?

2013年至2015年间,由于智能手机的发展,移动互联的异军突起,催生了大量的UI设计岗位,于是乎各种培训班如雨后春笋般冒了出来,成千上万的从事平面设计、室内设计、淘宝美工、前端开发等在职群体看到身边的人接二连三转型…

JMeter 接口测试教程,详解 HTTP Request 取样器和 fiddler 调试技巧!

目录 前言: 一、HTTP Request取样器介绍 二、使用HTTP Request取样器进行接口调试 1. 创建测试计划(Test Plan)和线程组(Thread Group) 2. 配置HTTP Request取样器参数 3. 添加断言 4. 运行接口测试 三、结合f…

Linux 企业级安全原理和防范技巧

Linux 企业级安全原理和防范技巧 1. 企业级Linux系统防护概述1.1 企业级Linux系统安全威胁1.2 企业级Linux系统安全立体式防范体系1.2.1 Linux文件系统访问安全1.2.2 Linux进程安全1. 进程的种类2. 进程管理方法 1.2.3 Linux用户管理安全1. 管理用户及组文件安全2. 用户密码管理…

2023年,8种必备Selenium编写自动化用例的技巧

在开始自动化时,您可能会遇到各种可能包含在自动化代码中的方法,技术,框架和工具。有时,与提供更好的灵活性或解决问题的更好方法相比,这种多功能性导致代码更加复杂。在编写自动化代码时,重要的是我们能够…

Java中枚举类的特殊用法-使用枚举实现单例模式和策略模式

场景 设计模式-单例模式-饿汉式单例模式、懒汉式单例模式、静态内部类在Java中的使用示例: 设计模式-单例模式-饿汉式单例模式、懒汉式单例模式、静态内部类在Java中的使用示例_霸道流氓气质的博客-CSDN博客 设计模式-单例模式-注册式单例模式-枚举式单例模式和容…

codeforces 1700A Optimal Path 贪心

说是贪心,想了一会,画个图辅助了解吧,我太菜了 如何证明蓝色格子的路线是最优解?只要证明红色线条的路线,可以不断地向右上方扭动身体,获得比原先路线更优的解。 比如8->13->14这个拐角,…

0117 1700

header aside-left content