第四周PTA笔记 好吃的巧克力+特殊的翻译+下次一定(续)+走迷宫
好吃的巧克力
超市正在特价售卖巧克力,正好被贪吃的Lucky_dog看见了。
巧克力从左到右排成一排,一共有N个,M种。
超市有一个很奇怪的规定,就是你在购买巧克力时必须提供两个数字a和b,代表你要购买第 a 个至第 b 个巧克力(包含 a 和 b)之间的所有巧克力。
假设所有巧克力的单价均为1元。Lucky_dog想吃所有种类的巧克力,但又想省钱。作为Lucky_dog的朋友,他请你来帮他决定如何选择购买巧克力时的 a 和 b。
输入格式:
第一行包含两个正整数 N 和 M(M<=N, N<=10^6 , M<=2000),分别代表巧克力的总数及种类数。
第二行包含 N 个整数,这些整数均在1 至 M 之间,代表对应的巧克力所属的种类。
输出格式:
输出仅一行,包含两个整数a和 b(a<=b) ,由一个空格隔开,表示花费最少且包含所有种类巧克力的购买区间。
数据保证有解,如果存在多个符合条件的购买区间,输出a最小的那个。
输入样例:
12 5
2 5 3 1 3 2 4 1 1 5 4 3
输出样例:
在这里给出相应的输出。例如:
2 7
如果没有大神相助,凭我自己的算法将会因为超时一直过不了,这道题源于洛谷P1638逛画展,这里的题解更丰富些,但我还是想在此总结一下自己的思路。
思路:从第一个数字开始将右端点右移,直到包括1到M的每一个数字并计算由1到M每一个数字的出现的次数,再检查左端点,若出现次数两次及两次以上,则将左端点右移,并将该数字的次数减一。这样可以确定一个初始区间,(查看题解后)更加完善了一下自己的代码,就是将之后的数字再遍历,按照确定初始区间的步骤,检查是否能取一个更小的区间。(比较巧妙的技术方法也是向大佬学的)
#include<stdio.h>
int a[1000000],b[2005];//全局变量初始值为0
int main()
{
long int N;
int M,r=0,i,R=0,L=1,R1,L1;
scanf("%ld%d",&N,&M);
for(i=0;i<N;i++)
{
scanf("%d",&a[i]);
}
i=0;
while(r!=M){
if(b[a[i]]==0)r++;
b[a[i]]++;
i++;
R++;
}//确定一个初始右端点
while(b[a[L-1]]>1){
b[a[L-1]]--;
L++;
} //右移左端点,缩小区间
R1=R;
L1=L;//确定初始区间
while(i<N){
b[a[i]]++;
R++;
i++;
while(b[a[L-1]]>1){
b[a[L-1]]--;
L++;
}
if(R-L<R1-L1){
R1=R;
L1=L;
}
}//遍历检查是否有更小的区间
printf("%d %d",L1,R1);
return 0;
}
特殊的翻译
小明的工作是对一串英语字符进行特殊的翻译:当出现连续且相同的小写字母时,须替换成该字母的大写形式,在大写字母的后面紧跟该小写字母此次连续出现的个数;与此同时,把连续的小写字母串的左侧和右侧的字符串交换位置;重复该操作,直至没有出现连续相同的小写字母为止。现在小明想请你帮他完成这种特殊的翻译。
输入格式:
输入一串由小写字母构成的字符串。(字符串长度不大于250)
输出格式:
输出翻译后的字符串。
输入样例1:
dilhhhhope
输出样例1:
在这里给出相应的输出。例如:
opeH4dil
输入样例2:
lodnkmgggggggoplerre
输出样例2:
在这里给出相应的输出。例如:
eG7lodnkmR2ople
刚开始思路很乱,主要在想字符串不相等如果再同一个数组当中不好处理,又或者在字符串中出现了好几个连续的字符串这也给我的解题思路蒙上了一层雾(就是思路很迷茫的委婉说法),在学习了其他同学的解题思路后,有了一个比较清晰的解题步骤了,现在先交代一下我的思路。
思路:首先题目并没有我所想的那么复杂,先找到第一个连续的字符串将其左右两边的字符串交换并且改变这个连续的字符串,接着再继续遍历,若有遇到一个连续字符串则重复以上步骤,直到整个字符串中没有连续的小字符串。大致思路就是这样,也有了个整体的框架。接着就是对于字符串交换的处理了,我新开了三个字符数组,分别用来存放左边字符,改变字符,右边字符。接着有个很重要的一步,就是将原本的字符串清零,然后再以右边字符,改变字符,左边字符的顺序赋给新的字符串。
感觉整体代码都很重要,我就直接附上全部代码了,在代码中我也将一些容易被忘记和忽略的情况标注出来了,方便解读。
#include<stdio.h>
#include<string.h>
char s1[250],s2[5],s3[250],s[250];
int main()
{
int n,i,t=1,a,b,x,j;
scanf("%s",s);
n=strlen(s);
for(i=0;i<n-1;i++)
{
if(s[i]==s[i+1]&&s[i]<123&&s[i]>96){//连续的字符串得是小写字母,必须附上这一判断,不然当字符个数为22或33时会出现差错
while(s[i]==s[i+1]){
t++;
i++;
}
a=i-t+1;
b=i+1;
for(x=b,j=0;s[x]!='\0';x++)
{
s3[j]=s[x];
j++;
}
strncpy(s1,s,a);
s2[0]=s[i]-32;
i=1;
memset(s,'\0',n);
if(t<10){
s2[i]=t+48;
n=a+2+j;
}
else if(t>9){
s2[i]=t/10+48;
i++;
s2[i]=t%10+48;
n=a+3+j;
}//对于连续的字符个数大于9的处理
for(i=0;i<j;i++)
{
s[i]=s3[i];
}
if(t<10){
s[i]=s2[0];
i++;
s[i]=s2[1];
i++;
}
else if(t>9){
s[i]=s2[0];
i++;
s[i]=s2[1];
i++;
s[i]=s2[2];
i++;
}//这一部分写得比较繁琐了,优点就是方便理解,嘿嘿嘿
for(x=0;x<a;x++)
{
s[i]=s1[x];
i++;
}
i=-1;//进入新的for循环后会i++,之后就会变为0
t=1;
}
}
printf("%s",s);
return 0;
}
下次一定(续)
你是一个bilibili的六级号,由于经常一键三连,所以一个硬币都没有,现在你又做了个梦,在梦中你制定了一个硬币增加规则:
第一天登陆后硬币总数1个,第二天登陆后硬币总数112个,第三天登陆硬币总数112123个......,以此类推,梦中不知日月,你瞬间拥有了11212312341234512345612345671234567812345678912345678910123456789101112345678910......无穷多个硬币。
常年维护B站秩序的百漂怪看不下去了,决定随机挑一个数x,作为这个无穷数的第x位,如果你能正确答对这第x位上的数是什么,就赠送给你与这个数等量的硬币。
百漂怪总共会挑t次。
你决定编程模拟一下,搏一搏,单车变摩托。
输入格式:
第一行包含一个正整数t(1≤t≤10),表示百漂怪挑了t次。 接下来t行,每行一个正整数x (1 ≤ x≤ 2^31-1),表示第i次,百漂怪挑的是第x位。
输出格式:
输出共t行,每行输出对应第x位上的数。
输入样例1:
2
3
8
输出样例1:
2
2
输入样例2:
6
222
66666
99999999
66656565
22222
2
输出样例2:
6
4
9
4
1
1
思路:一开始完全暴力解法,于是时间超出,就采用了半暴力解法(自创名词哈哈哈)。由于这组数据很大,我们不能将它全部存于一个数组,所以我们得一部分一部分地存。一开始先判断百漂怪所给的数字是属于哪一部分的数,比如3,那前个数是112,那这就是第二部分的数字,不知道我有没有说清楚,但题目意思大概就是酱紫。判断完了之后判断这个最初的数是这部分的哪一个数字,最后得出结果。
一开始判断是哪一部分的数字我由于写得太复杂了,时间超出,我是直接用一个数字n一直递增来减去最初的数字。
//错误代码
scanf("%d",&x);
j=1;
while(x>0){
if(j<10){
n++;
x-=n;
j++;
}
else if(j<100&&j>9){
n+=2;
x-=n;
j++;
}
else if(j>99&&j<1000){
n+=3;
x-n;
j++;
}
else if(j>999&&j<10000){
n+=4;
x-n;
j++;
}
else if(j>9999&&j<100000){
n+=5;
x-n;
j++;
}
}
x+=n;
后来这部分我改进了一下,时间超出的问题就解决了,虽然也不是特别高明。我现在还太菜鸡,其实对于算法时间复杂度的概念还很模糊。
//正确代码
for(i=0;i<32000;i++)
{ y=i;
if(i==0)a[i]=1;
else a[i]=a[i-1]+(int)(log10(y+1)+1);
}//存位数
for(j=0; ;j++)
{
x-=a[j];
if(x<=0)break;
}
x+=a[j];
通过其他同学的博客,直到这个数据总共有31268组,于是我将后面的判断由100以内,扩大到了100000以内,以下是判断具体数字的代码。
j=1;
for(r=0; ;j++)
{
if(j<10){
n=j;
r++;
if(r==x)break;
}
else if(j>9&&j<100){
n=j/10;
r++;
if(r==x)break;
n=j%10;
r++; if(r==x)break;
}
else if(j>99&&j<1000)
{
n=j/100;
r++;if(r==x)break;
n=j/10%10;
r++;if(r==x)break;
n=j%10;
r++;if(r==x)break;
}
else if(j>999&&j<10000)
{
n=j/1000;
r++;if(r==x)break;
n=j%1000/100;
r++;if(r==x)break;
n=j%100/10;
r++;if(r==x)break;
n=j%10;
r++;if(r==x)break;
}
else if(j>9999&&j<100000)
{
n=j/10000;
r++;if(r==x)break;
n=j%10000/1000;
r++;if(r==x)break;
n=j%1000/100;
r++;if(r==x)break;
n=j%100/10;
r++;if(r==x)break;
n=j%10;
r++;if(r==x)break;
}
}
printf("%d\n",n);
走迷宫
你正在玩一个迷宫游戏,迷宫有n×n格,每一格有一个数字0或1,可以从某一格移动到相邻四格中的一格上。为了消磨时间,你改变了玩法,只许从0走到1或者从1走到0。
现在给你一个起点,请你计算从这个格子出发最多能移动多少个格子(包含自身)。
输入格式:
第1行包含两个正整数n和m(1≤n≤1000,1≤m≤10000)。
接下来n行,对应迷宫中的n行,每行n个字符,字符为0或者1,字符之间没有空格。
接下来m行,表示m次询问。每行2个正整数i,j,表示从迷宫中第i行第j列的格子开始走。
输出格式:
输出共m行,每行一个整数,分别对应于输入数据中的m次询问,给出最多能移动的格子数。
输入样例:
2 2
01
10
1 1
2 2
输出样例:
4
4
因为这道题让我的这篇博客居然拖到今天才写完,一开始对于没接触过这样题型的我的思路就是一个一个地找,对,没错,酱紫是行不通的。于是在多次查阅资料下了解了dfs和bfs,其实我也没有理解透,但勉勉强强能应付这题吧。这一题的原题在P1141迷宫并且一起在此打包上题解了。这个up主的视频也有助于理解dfs和bfs,个人感觉他的dfs讲得好一些。
一些注意事项和解题思路我就在代码当中直接标记出来了,因为这次的解题就是主要用到dfs(通过递归实现),所以感觉也没啥好说的。
#include<stdio.h>
#include<string.h>
int n,b[1005][1005],z[100005],i;//z数组是存每一个能够走的最大距离,需要开得大一点,不然会出现RE的问题
char s[1005][1005];
void dfs(int x,int y,int f);
int main()
{
int m,c,d;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%s",s[i]);//一开始用%c来存,一直输出不了,应该是因为一行之间的0或1没有其他字符隔开,无法判断输出结束了吧
}
memset(b,-1,sizeof(b));//将b数组初始化为-1,这为了判断是否有走过这一格的数组。一开始初始化为0,但是当i=0时这个就没法走了[哭脸]
for(i=0;i<m;i++)
{
scanf("%d%d",&c,&d);
c--;
d--;
if(b[c][d]==-1)dfs(c,d,s[c][d]-48);//将字符数组转换为0和1比较方便于判断
else z[i]=z[b[c][d]];//如果b数组已经被赋值,说明已经走过了这个各自,可以通过已经存储在a中的数字来读出,可以节省时间
}
for(i=0;i<m;i++)
{
printf("%d\n",z[i]);
}
return 0;
}
void dfs(int x,int y,int f)
{
if(x<0||x>=n||y<0||y>=n)return;//判断是否在迷宫范围内;
else{
if(b[x][y]==-1&&s[x][y]-48==f){//判断该格子是否走过且是否与上一个格子的字符相同
b[x][y]=i;
z[i]++;
dfs(x+1,y,!f);//这个!f得想一想,就是取上一个格子的字符的相反数,体现了将字符元素改为0和1的好处了吧
dfs(x-1,y,!f);
dfs(x,y+1,!f);
dfs(x,y-1,!f);
}
else return;
}
}
如果有写的不好或说的错误的地方,欢迎指出哦。
第四周PTA笔记 好吃的巧克力+特殊的翻译+下次一定(续)+走迷宫的更多相关文章
- 20165326 java第四周学习笔记
第四周学习笔记 ch5 子类和父类 子类只能有一个父类 使用关键字extendsyclass 子类 extends 父类 系统默认的祖先类Object(java.lang包中) 继承:子类继承父类的方 ...
- 《Linux内核分析》第四周学习笔记
<Linux内核分析>第四周学习笔记 扒开系统调用的三层皮(上) 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.c ...
- 《Linux内核设计与实现》第四周读书笔记——第五章
<Linux内核设计与实现>第四周读书笔记--第五章 20135301张忻 估算学习时间:共1.5小时 读书:1.0 代码:0 作业:0 博客:0.5 实际学习时间:共2.0小时 读书:1 ...
- linux内核分析第四周学习笔记
linux内核分析第四周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- 20155327 java第四周学习笔记
20155327 java第四周学习笔记 五六章知识整理 1子类与父类 父类是接口或者是抽象类,子类必须继承自父类. 2子类的继承性 在Java中,通过关键字extends继承一个已有的类,被继承的类 ...
- Jinja2学习笔记暨官方文档的翻译
http://blog.csdn.net/lgg201/article/details/4647471 呵呵, 刚刚看完Python模板引擎Jinja2的文档, 感觉很好, 觉得动态语言真是很好. ...
- Linux内核分析——第四周学习笔记20135308
第四周 扒开系统调用的“三层皮” 一.内核.用户态和中断 (一)如何区分用户态.内核态 1.一般现在的CPU有几种不同的指令执行级别 ①在高级别的状态下,代码可以执行特权指令,访问任意的物理地址,这种 ...
- Linux内核分析——第四周学习笔记
扒开系统调用的三层皮[上] 前言:以下笔记除了一些讲解视频中的概念记录,图示.图示中的补充文字.总结.分析.小结部分均是个人理解.如有错误观点,请多指教! 补充:[系统调用的参数传递方法]视频中讲解简 ...
- 20179223《Linux内核原理与分析》第四周学习笔记
补交第三周作业 完成一个简单的时间片轮转多道程序内核 1.使用实验楼的虚拟机打开shell,用cd LinuxKernel/linux-3.9.4进入linux-3.9.4. 2.执行命令qemu - ...
随机推荐
- 2017年第二届广东省强网杯线上赛WEB:Musee de X writeup(模板注入漏洞)
目录 解题思路 总结 解题思路 拿到手上,有四个页面 首先按照题目要求执行,尝试注册一个名为admin的账户 这种情况,路径都给出来了,很可能就是目录遍历或者文件上传了 回到初始界面,点击链接here ...
- 解决Vue项目打包之后放到nginx下刷新就报错404的问题
最近跟着某机构的教学视频敲了一遍vue项目,但是在windows环境下部署的时候就懵逼了放到nginx下正常跑没问题,但是刷新之后就报404错误 前端项目构建vue 脚手架版本 是@vue/cli 4 ...
- Redis对象
概述 Redis并没有使用基础数据结构去实现键值数据库,而是基于数据结构封装了一个个对象. 类型和编码 由于Redis是键值数据库,所以每次存储数据时,至少包含两个对象,即K.V对应的对象.其数据结构 ...
- 前端VUE基于gitlab的CI_CD
目录 CI 1.Gitlab的CI 1.1 GitLab-Runner 1.2 .gitlab-ci.yml 1.3 配置.gitlab-ci.yml 1.3.1 Pipeline概念 1.3.2 S ...
- UE4蓝图AI角色制作(三)
接上一节 6. 寻路网格体代理 通过允许配置多个"代理",虚幻引擎使得用户能够轻松为大小各异的AI创建寻路网格体.首先,选中世界大纲视图中的"RecastNavMesh& ...
- JVM学习笔记——堆
堆 Heap 一个 JVM 只有一个堆,堆也是 Java 内存管理的核心区域.在 JVM 启动时堆被创建,同时大小在启动时已设定好,堆是 JVM 管理最大的一块内存空间,其大小可以调节. 堆的内存空间 ...
- 高中最后一刻&大学第一课&为人师的责任
文章不是技术文,只是分享一些感想,作为一只程序猿,不说好好敲代码,跑出来思考人生,不是合格的程序猿,罪过罪过,自我反思3秒钟,我们继续,毕竟程序猿的人生不只是Coding,也希望自己这点感想被更多刚入 ...
- 一文读懂 Serverless,将配置化思想复用到平台系统中
作者 | 春哥大魔王 来源 | Serverless 公众号 写在前面 在 SaaS 领域 Salesforce 是佼佼者,其 CRM 的概念已经扩展到了 Marketing.Sales.Servic ...
- 2020.3.21--ICPC训练联盟周赛Benelux Algorithm Programming Contest 2019
A Appeal to the Audience 要想使得总和最大,就要使最大值被计算的次数最多.要想某个数被计算的多,就要使得它经过尽量多的节点.于是我们的目标就是找到 k 条从长到短的链,这些链互 ...
- Java---String和StringBuffer类
Java---String和StringBuffer类 Java String 类 字符串在Java中属于对象,Java提供String类来创建和操作字符串. 创建字符串 创建字符串常用的方法如下: ...