ccf-csp 202112-3登机牌条码

news2024/11/17 17:53:56

题目背景

西西艾弗岛景色优美,游人如织。但是,由于和外界的交通只能靠渡船,交通的不便严重制约了岛上旅游业的发展。西西艾弗岛管委会经过努力,争取到了一笔投资,建设了一个通用航空机场。在三年紧锣密鼓的主体建设后,西西艾弗岛通用航空机场终于开始进行航站楼内部软硬件系统的安装和调试工程了。小 C 是机场运营公司信息部的研发工程师,最近,信息部门的一项重要任务是,研发登机牌自助打印系统。如图所示的是设计部门根据国际民航组织的行业标准设计的登机牌样张。

登机牌上最重要的部分就是最下方的机读条形码了。小 C 承担了生成机读条形码算法的开发工作。从被编码的数据到条形码,中间有好多步骤要走。小 C 请你来帮忙,让你帮忙处理一下数据编码的问题。

题目描述

登机牌上的条形码,是 PDF417 码。PDF417 码的结构如下图所示。

PDF417 码组成的基本元素是码元(Module),所有的码元都是等大的矩形,填充有黑色或白色。码元先组成行,若干行堆叠组成整个 PDF417 码。每一行中,每 17 个码元表示一个码字(Code word)。码字是 PDF417 编码中的最小数据单位。每个码字图案中,有交替排列的四个黑色矩形和四个白色矩形,这便是 “417” 的由来。每行开始和结尾有固定的起始和中止图案。与他们相邻的是行左侧和右侧标志,表示行号、行内码字个数等信息。中间的是有效数据区。编码的步骤是:先按照编码规则,将被编码的数据转换为码字;接着根据选定 PDF417 码的宽度(即每行码字的数目)以及冗余程度计算校验码字;最后将码字按规则转换为对应的图案,并按照从左至右,从上至下的的顺序填入有效数据区,并与起始终止图案和行左右标志拼合,形成完整的 PDF417 码。

每个码字是一个 0 至 928 之间的数字,每个码字可以编码两个输入字符。对于输入的被编码的数据,按照下表进行编码。编码器共有三种模式:大写字母模式、小写字母模式和数字模式。在编码开始时,编码器处于大写字母模式。编码器处于某种模式时,仅能编码对应类型的字符,如果需要编码其它类型的字符,需要通过特殊值切换到对应模式下。要进行模式切换,可以有多种切换方法。例如,要从大写模式切入小写模式,可以直接用 27 切入,也可以先用 28 切入数字模式后立刻再用 27 切入小写模式。你需要选择最短的方式进行切换,因此只有前一种方法是正确的。需要注意的是,从小写模式不能直接切入大写模式,必须要经过数字模式过渡。

大写模式小写模式数字模式
0Aa0
1Bb1
2Cc2
3Dd3
4Ee4
5Ff5
6Gg6
7Hh7
8Ii8
9Jj9
10Kk
11Ll
12Mm
13Nn
14Oo
15Pp
16Qq
17Rr
18Ss
19Tt
20Uu
21Vv
22Ww
23Xx
24Yy
25Zz
27小写小写
28数字数字大写
29填充填充填充

按照这个方法可以得到一系列的不超过 30 的数字。如果有奇数个这样的数字,则在最后补充一个 29,使之成为偶数个。将它们两两成组,假设 H 和 L 是一组中连续出现的两个数字,那么可以得到一个码字是:
30×H+L

例如,要编码 “HE1lo”,首先先根据字母表,产生数字序列:

H E    1    l  o
7 4 28 1 27 11 14

由于只有奇数个数字,需要在末尾补充 29,然后将它们两两成组:

(7, 4), (28, 1), (27, 11), (14, 29)

最后计算码字,例如:30×7+4=214,以此类推,可以得到码字为:

214, 841, 821, 449

接下来要计算校验码。校验码字的数目,由校验级别确定。假设校验级别为 s(0≤s≤8),则校验码字的数目为 k=2s+1。特别地,如果指定了 s=−1,则表示不需要计算校验码字。要计算校验码字,首先要确定数据码字。数据码字由以下数据按顺序拼接而成(如图所示):

  • 一个长度码字,表示全部数据码字的个数 n,包括该长度码字、有效数据码字、填充码字;
  • 若干有效数据码字,是此前计算的码字序列;
  • 零个或多个由重复的 900 组成的填充码字,使得包括校验码字在内的码字总数恰能被有效数据区的行宽度整除。

设全部数据码字依次为 dn−1,dn−2,…,d0;校验码字依次为 ck−1,ck−2,…,c0。那么校验码字按照如下方式计算:

取 k 次多项式 g(x)=(x−3)(x−32)…(x−3k), (n−1) 次多项式 d(x)=dn−1xn−1+…dn−2xn−2+…d1x+d0,找到多项式 q(x) 和不超过 (k−1) 次的多项式 r(x),使得
xkd(x)≡q(x)g(x)−r(x)。那么多项式 r(x) 中 x 的 i 次项系数对 929 取模后(取正值)的数字即为校验码字 ci。

例如,如果要将 HE1lo 编码为 PDF417 条码,且有效数据区的行宽是 4 码字(即 68 码元),校验级别为 0。此时校验码字有两个。根据此前的编码结果,有效数据码字有 4 个。再加上一个长度码字,共有 7 个码字。因此需要补充一个填充码字,使包括校验码字在内的总码字数能够被 4 整除。这样,用于计算校验码字的数据码字有 6 个,分别是:

6, 214, 841, 821, 449, 900

因此有 g(x)=x2−12x+27,d(x)=6x5+214x4+841x3+821x2+449x+900,不难得到 r(x)=−32902164x+98246277,因此相应可以计算出 c1=229≡−32902164mod929,c0=811≡98246277mod929。这样,全部码字序列即为:

6, 214, 841, 821, 449, 900, 229, 811

在本题中,你需要帮助小 C 完成的任务是,给定被编码的数据,计算出需要填入有效数据区的码字序列。被处理的数据中只含有大写字母、小写字母和数字。

输入格式

从标准输入读入数据。

输入的第一行包含两个用空格分隔的整数 w、s,分别表示有效数据区每行能容纳的码字数和校验级别。保证 0<w<929,−1≤s≤8。特别地,当 s=−1 时,表示不需要计算校验码字。

输入的第二行是一个非空字符串,仅包含大小写字母和数字,长度保证编码后全部数据码字的个数少于 929。

输出格式

输出到标准输出。

输出若干行,每行一个数字,表示编码后的全部码字序列。

样例1输入

5 -1
HELLO

样例1输出

5
214
341
449
900

样例1解释

要求编码数据是 HELLO,首先查表将其对应成数字。注意,由于编码器在开始时就处于大写字母模式,因此不需要额外的模式切换。因此对应成的数字为:7, 4, 11, 11, 14。由于只有奇数个数字,因此补充 29,形成序列 7, 4, 11, 11, 14, 29。然后两两成组计算码字:7×30+4=214,以此类推,得到 214, 341, 449。本输入不要求产生校验码,且有效数据区的宽度是 5 码字。目前有效数据的码字是 3 个,加上开头要添加的长度码字,共有 4 个码字。因此,需要补充一个填充码字,使得总码字数达到 5 个,充满一行。注意,长度码字中的长度数据包括所有数据码字,因此长度码字是 5 而不是 4。最终可以得到码字序列 5, 214, 341, 449, 900

样例1输入

4 0
HE1lo

样例1输出

6
214
841
821
449
900
229
811

样例2解释

本组数据即为此前用于说明编码过程的示例。

子任务

对于 20% 的数据,有 s=−1,且输入字符串中仅含有大写字母或小写字母;

对于 40% 的数据,有 s=−1;

对于 80% 的数据,有 s≤2;

对于 100% 的数据,满足全部对于输入的要求。

注释

 

#include<bits/stdc++.h>
using namespace std;
const int mod=929;
const int N=1000010;
int w,s,k;
string str;
int f[N];//记录str
int zu[N];//记录30*x1+x2 
int g[N],d[N];

int main()
{
	cin>>w>>s;
	cin>>str;
	//处理校验码字的数目k
	if(s==-1) k=0;
	else 
	{
		k=pow(2,s+1);
	}
	
	int step=1;//1表示大写,2表示小写,3表示数字 
	int num=0;//num表示当前有多少数字
	
	//处理str字符串,产生数字序列 
	for(int i=0;i<str.size();i++)
	{
		if(str[i]>='A' && str[i]<='Z')
		{
			if(step==1)
			{
				f[num++]=str[i]-'A';
			}
			else if(step==2)
			{
				f[num++]=28;
				f[num++]=28;
				f[num++]=str[i]-'A';
			}
			else if(step==3)
			{
				f[num++]=28;
				f[num++]=str[i]-'A';
			}
			step=1;
		}
		if(str[i]>='a' && str[i]<='z')
		{
			if(step==1)
			{
				f[num++]=27;
				f[num++]=str[i]-'a';
			}
			else if(step==2)
			{
				f[num++]=str[i]-'a';
			}
			else if(step==3)
			{
				f[num++]=27;
				f[num++]=str[i]-'a';
			}
			step=2;
		}
		if(str[i]>='0' && str[i]<='9')
		{
			if(step==1)
			{
				f[num++]=28;
				f[num++]=str[i]-'0';
			}
			else if(step==2)
			{
				f[num++]=28;
				f[num++]=str[i]-'0';
			}
			else if(step==3)
			{
				f[num++]=str[i]-'0';
			}
			step=3;
		}
	}
	// for(int i=0;i<num;i++) { cout << f[i]<<" "; }
	if(num%2==1)
	{
		f[num++]=29;
	}
	
	//将数字序列两两成组 
	int numzu=0;
	for(int i=0;i<num;i+=2)
	{
		zu[numzu++]=f[i]*30+f[i+1]; 
	}
	// for(int i=0;i<numzu;i++) { cout << zu[i]<<" ";	}
	
	//判断是否需要添加辅助码
	int summ=numzu+1+k;
	if(summ%w!=0)
	{
		int mm=w-summ%w;
		for(int i=1;i<=mm;i++)
		{
			zu[numzu++]=900;
		}
	} 
	
	//输出长度码字
	cout << numzu+1 <<endl;
	
	//输出成组
	for(int i=0;i<numzu;i++)
	{
		cout << zu[i]<<endl;
	}
	
	//校验码:
	
	//g[x] 
	int chang=-3;
	g[0]=1;
	for(int i=0;i<k;i++)
	{
		for(int j=i;j>=0;j--)
		{
			g[j+1]=(g[j+1]+g[j]*chang)%mod;
		}
		chang=chang*3%mod;
	}
	// for(int i=0;i<=k;i++) {	cout << g[i]<<" "; }
	
	//d[x]
	d[0]=numzu+1;
	for(int i=1;i<=numzu;i++) 
	{
		d[i]=zu[i-1];
	}
	// for(int i=0;i<=numzu;i++) {	cout << d[i]<<" "; }
	
	//r[x]?????
	for(int i=0;i<=numzu;i++)
	{
		for(int j=1;j<=k;j++)
		{
			d[i+j]=(d[i+j]-g[j]*d[i])%mod;
		}
	}
	
	//输出校验码
	for(int i=numzu+1;i<=numzu+k;i++)
	{
		cout << (mod-d[i]%mod)%mod <<endl;
	}
}
/*
4 0
HE1lo
*/ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/398634.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jetpack Compose 中的动态加载、插件化技术探索

在传统的 Android 开发模式中&#xff0c;由于界面过分依赖于 Activity、Fragment这样的组件&#xff0c;一个业务模块中往往会存在着大量的 Activity 类&#xff0c;因此诞生了很多的插件化框架&#xff0c;这些插件化框架基本都是想方设法的使用各种Hook/反射手段来解决使用未…

c++11auto

autoc11中auto并不代表一种实际的数据类型&#xff0c;它只是一个类型声明的占位符&#xff0c;auto也并不是再所有场景下都能推导出变量的实际类型&#xff0c;使用auto不需要进行初始化&#xff0c;让编译器推导出它的实际类型&#xff0c;再编译阶段将auto占位符替换为真正的…

没有比这更详细的-压测工具Jmeter介绍及使用了

一、压测工具选型 1.1、前言 压力测试是每一个Web应用程序上线之前都需要做的一个测试&#xff0c;他可以帮助我们发现系统中的瓶颈问题&#xff0c;减少发布到生产环境后出问题的几率&#xff1b;预估系统的承载能力&#xff0c;使我们能根据其做出一些应对措施。所以压力测…

【Linux基础篇】一、Linux入门基础命令

一、Linux基础命令 1、Linux的目录结构 /&#xff0c;根目录是最顶级的目录了Linux只有一个顶级目录&#xff1a;/路径描述的层次关系同样适用/来表示/home/itheima/a.txt&#xff0c;表示根目录下的home文件夹内有itheima文件夹&#xff0c;内有a.txt 2、ls命令 功能&#…

数字孪生GIS智慧风场Web3D可视化运维系统

随着国家双碳目标的实施&#xff0c;新能源发电方式逐渐代替了污染大气层的火力发电&#xff0c;其中风力发电相比于光伏发电具有能量密度高、发电小时数长、生命周期达20-25年之久等独特的优势。风能取之不尽、用之不竭&#xff0c;在新型能源互联网下&#xff0c;风力发电有可…

三、GC算法垃圾回收器

文章目录&#xff08;持续更新中... ...CMS and G1&#xff09;概述如何判断对象存活引用计数法根可达算法GC算法(垃圾回收算法)分代收集理论标记-清除算法复制算法标记-整理算法垃圾回收器概述Serial收集器Parallel收集器Parallel Old收集器CMS收集器G1收集器常用的收集器组合…

STM32实战项目-串口打印

前言&#xff1a; 本小结主要实现串口打印功能&#xff0c;主要将上一结的状态机运行次数&#xff0c;通过串口在串口终端上打印出来&#xff0c;硬件电路上主要是TTL转USB驱动电路&#xff0c;软件上主要有状态机函数&#xff0c;串口发送函数等调试工具是串口助手。 目录 1…

机器学习学习记录1:假设空间

我们可以把学习过程看作一个在所有假设组成的空间中进行搜索的过程&#xff0c;搜索目标是找到与训练集"匹配" 的假设&#xff0c;即能够将训练集中的瓜判断正确的假设.假设的表示一旦确定&#xff0c;假设空间及其规模大小就确定了.对于西瓜问题&#xff0c;这里我们…

[MySQL索引]2.索引的底层原理(一)

索引的底层原理&#xff08;一&#xff09;B-树索引B树索引tips: ​ 通过使用malloc/new来申请4字节的内存&#xff0c;但是操作系统不是说每一次用户申请4字节内存&#xff0c;我就只分配4字节&#xff0c;这样申请次数多了就要涉及频繁的用户态和内核态的切换&#xff0c;开销…

AM5728(AM5708)开发实战之安装Debian 10桌面操作系统

一 环境搭建 准备一个SD卡启动卡&#xff0c;能够正常引导板卡启动&#xff0c;后续会把Debian 10镜像安装到SD卡ext4分区 准备两个U盘&#xff0c;一个格式化成fat32文件系统&#xff0c;另一个格式化成ext4文件系统 下载Debian 10镜像&#xff0c;镜像名字为debian-10.4.0-a…

【前端】一个更底层库React,附教程

Reat是什么&#xff1f;React在UI里最火的也是最好的库&#xff0c;React是一个做UI的库&#xff0c;具体来说是做UI组件的库&#xff0c;专注于做mvc中的v&#xff0c;它是一个更底层的工具库。为你应用的每一个状态设计简洁的视图&#xff0c;当数据变动时 React 能高效更新并…

Linux发行版本与发行版的简单的介绍

Linux linux下有很多发行的版本&#xff0c;或者称之为魔改版本。以下介绍一些常见的版本&#xff0c;以避免名词的混淆。 linux是提供了一个内核&#xff0c;就像是谷歌的内核一样&#xff0c;QQ浏览器就是使用的谷歌的内核&#xff0c;也算是一个发行版本。 Ubuntu&#x…

课程项目简介

一、深度学习模型入门 1&#xff0c;什么是机器学习&#xff1f; Study of algorithms that improve their performance P at some task T with experience E. 研究在某个任务T上用经验E提高其性能P的算法。 well-defined learning task:<P,T,E> 明确的学习任务&#…

手把手开发一门程序语言JimLang (2)

根据爱因斯坦的相对论&#xff0c;物体的质量越大&#xff0c;时间过得越快&#xff0c;所以托更对于我的煎熬&#xff0c;远远比你们想象的还要痛苦…今天给大家来盘硬菜&#xff0c;也是前些时日预告过的JimLang的开发过程… Let’s go !!! 语法及解析 JimLang.g4 这里我们…

轮毂要怎么选?选大还是选小?

随着改装车的越来越火爆&#xff0c;汽车轮毂可选择的款式也越来越多&#xff0c;90%的人换轮毂&#xff0c;首先选的就是外观。大轮毂的款式多&#xff0c;外形大气好看&#xff0c;运动感十足&#xff0c; 那是不是选大轮毂就可以呢&#xff1f;不是的&#xff0c;汽车轮毂要…

全面吃透Java Stream流操作,让代码更加的优雅

文章目录1 认识Stream流1.1 什么是流1.2 流与集合1.2.1 流只能遍历一次1.2.2 外部迭代和内部迭代1.3 流操作1.3.1 中间操作1.3.2 终端操作1.3.3 使用流2 学会使用Stream流2.1 筛选和切片2.1.1 用谓词筛选2.1.2 筛选各异的元素2.1.3 截短流2.1.4 跳过元素2.2 映射2.2.1 map方法2…

Java经典面试题——对比 Vector、ArrayList、LinkedList 有何区别?

典型回答 这三者都是实现集合框架中的 List &#xff0c;也就是所谓的有序集合&#xff0c;因此具体功能也比较近似&#xff0c;比如都提供按照位置进行定位、添加或者删除的操作&#xff0c;都提供迭代器以遍历其内容等。但因为具体的设计区别&#xff0c;在行为、性能、线程…

详解CRC原理以及C语言实现

CRC检验原理 CRC&#xff08;Cyclic Redundancy Check&#xff09;校验是一种常用的数据校验方法&#xff0c;它通过计算数据的校验码来检测数据在传输过程中是否出现了错误。 CRC校验的基本原理是将数据按照一定的规则进行计算&#xff0c;得到一个固定长度的校验码&#xf…

JavaScript内改变this指向

之前我们说的都是代码内 this 的默认指向 今天我们要来说一下如何能改变 this 指向 也就是说, 你指向哪我不管, 我让你指向哪, 你就得指向哪 开局 在函数的原型( Function.prototype ) 上有三个方法 call apply bind 既然是在函数的原型上, 那么只要是函数就可以调用这三个方…

React(七):Router基本使用、嵌套路由、编程式导航、路由传参、懒加载

React&#xff08;七&#xff09;一、React-Router的基本使用1.安装和介绍2.路由的配置和跳转3.Navigate的使用4.如果找不到对应的路由路径&#xff1f;二、嵌套路由的用法三、编程式路由导航1.类组件中使用useNavigate2.函数式组件中使用useNavigate四、路由跳转传参1.设置好路…