好吃的巧克力

超市正在特价售卖巧克力,正好被贪吃的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笔记 好吃的巧克力+特殊的翻译+下次一定(续)+走迷宫的更多相关文章

  1. 20165326 java第四周学习笔记

    第四周学习笔记 ch5 子类和父类 子类只能有一个父类 使用关键字extendsyclass 子类 extends 父类 系统默认的祖先类Object(java.lang包中) 继承:子类继承父类的方 ...

  2. 《Linux内核分析》第四周学习笔记

    <Linux内核分析>第四周学习笔记 扒开系统调用的三层皮(上) 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.c ...

  3. 《Linux内核设计与实现》第四周读书笔记——第五章

    <Linux内核设计与实现>第四周读书笔记--第五章 20135301张忻 估算学习时间:共1.5小时 读书:1.0 代码:0 作业:0 博客:0.5 实际学习时间:共2.0小时 读书:1 ...

  4. linux内核分析第四周学习笔记

    linux内核分析第四周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

  5. 20155327 java第四周学习笔记

    20155327 java第四周学习笔记 五六章知识整理 1子类与父类 父类是接口或者是抽象类,子类必须继承自父类. 2子类的继承性 在Java中,通过关键字extends继承一个已有的类,被继承的类 ...

  6. Jinja2学习笔记暨官方文档的翻译

    http://blog.csdn.net/lgg201/article/details/4647471 呵呵, 刚刚看完Python模板引擎Jinja2的文档, 感觉很好, 觉得动态语言真是很好.  ...

  7. Linux内核分析——第四周学习笔记20135308

    第四周 扒开系统调用的“三层皮” 一.内核.用户态和中断 (一)如何区分用户态.内核态 1.一般现在的CPU有几种不同的指令执行级别 ①在高级别的状态下,代码可以执行特权指令,访问任意的物理地址,这种 ...

  8. Linux内核分析——第四周学习笔记

    扒开系统调用的三层皮[上] 前言:以下笔记除了一些讲解视频中的概念记录,图示.图示中的补充文字.总结.分析.小结部分均是个人理解.如有错误观点,请多指教! 补充:[系统调用的参数传递方法]视频中讲解简 ...

  9. 20179223《Linux内核原理与分析》第四周学习笔记

    补交第三周作业 完成一个简单的时间片轮转多道程序内核 1.使用实验楼的虚拟机打开shell,用cd LinuxKernel/linux-3.9.4进入linux-3.9.4. 2.执行命令qemu - ...

随机推荐

  1. bzoj#4722-由乃【倍增,抽屉原理,bitset】

    正题 题目链接:https://darkbzoj.tk/problem/4722 题目大意 给出一个长度为\(n\)的序列值域为\([0,v)\),要求支持操作 询问一个区间能否找到两个没有交的非空下 ...

  2. 📝 没 2 年 React Native 开发经验,你都遇不到这些坑

    如果你喜欢我的文章,希望点赞 收藏 评论 三连支持一下,谢谢你,这对我真的很重要! React Native 开发时,如果只是写些简单的页面,基本上按着官方文档 reactnative.dev就能写出 ...

  3. HCNP Routing&Switching之路由引入

    前文我们了解了路由控制技术策略路由相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15333139.html:今天我们来聊一聊路由引入技术相关话题: 路 ...

  4. HttpRunner3.X - 全面讲解如何落地项目实战

    一.前言 接触httprunner框架有一段时间了,也一直探索如何更好的落地到项目上,本篇主要讲述如何应用到实际的项目中,达到提升测试效率的目的. 1.项目难题 这个月开始忙起来了,接了个大项目,苦不 ...

  5. Django整理(一) - 项目和应用创建及运行

    一.项目组织结构     · 一个Project包含有多个App     · 一个App就是一个Python包,就代表一个功能模块,比如: 用户模块,商品模块等 .各个功能模块间可以保持相对的独立 . ...

  6. Java到底怎么学?

    你现在是不是想学Java,但很迷茫不知该从何下手,那么请认真看完这篇文章,希望对你有所帮助! 作为零基础刚刚接触Java的朋友们来说,我的建议还是先看视频,虽然有很多人说看视频学习慢,建议直接买优秀的 ...

  7. python jinja2初见

    吸取了长城杯的教训,学习python-web迫在眉睫. 正常难度的python_template_injection,由于现在没学面向对象,理解原理比较困难,所以先使用简单版复现:并附上正常版的常用p ...

  8. 安装多个版本的 JDK

    安装多个版本的 JDK 刚刚开始学 Java 的时候安装了 JDK9 版本,后续发现还是 JDK8 使用的多些,而又不想删除原先版本 因此安装两个版本的 JDK 在需要是切换一下即可 1. 安装第一个 ...

  9. 【Linux命令063】Linux非常简单常用的入门命令

    Linux常用命令 这是一篇我在公众号上发布的文章,还算较为受欢迎. 博客园这边荒废好长时间了,主要是最近一年经常撰写的文章都是Linux相关的入门文章. 不知道是否能通过博客园的首页审核. 1.cd ...

  10. VS2019、Qt5.12及QGis3.16开发常见问题汇总

    在C++.Qt软件开发过程中,常常遇到一些编译错误或警告:本文将VS2019.Qt5.12.10和QGis3.16.10的二次开发过程常见的问题做了整理,供大家参考,也便于日后查阅.该内容分为四部分: ...