好吃的巧克力

超市正在特价售卖巧克力,正好被贪吃的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. Spring,AOP实现功能级别权限验证

    1. 首先是问题出现的原因 对于一个我的一个个人博客网站,我希望游客可以浏览我的博客,但是评论功能是需要登录才能使用 这就需要对某个功能进行权限验证 对于过滤器,拦截器,AOP的区别日后再讨论,现在是 ...

  2. kubectl 的插件管理工具krew

    k8s的命令行工具kubectl 对于玩k8s 的人来说是必备工具.kubectl插件机制在Kubernetes 1.14宣布稳定,进入GA状态.kubectl的插件机制就是希望允许开发者以独立的二进 ...

  3. Vue router中携带参数与获取参数

    Vue router中携带参数与获取参数 携带参数 query方式,就是?+&结构,例如/login?id=1 <router-link :to="{ name:'login' ...

  4. java 文档自动生成的神器 idoc

    写文档 作为一名开发者,每个人都要写代码. 工作中,几乎每一位开发者都要写文档. 因为工作是人和人的协作,产品要写需求文档,开发要写详细设计文档,接口文档. 可是,作为一个懒人,平时最讨厌的一件事情就 ...

  5. CF536D Tavas in Kansas(博弈论+dp)

    貌似洛谷的题面是没有翻译的 QWQ 大致题面是这个样子,但是可能根据题目本身有不同的地方 完全懵逼的一个题(果然博弈论就是不一样) 首先,我们考虑把题目转化成一个可做的模型. 我们分别从\(s\)和\ ...

  6. allure报告中allure.title 如何去掉后方的参数化显示

    1.解决方法如下 listener.py 文件位置:Lib\site-packages\allure_pytest\listener.py (第三方包所在的LIb目录) 将下图中红色部分test_re ...

  7. Java(13)详解构造方法

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201600.html 博客主页:https://www.cnblogs.com/testero ...

  8. 【Java虚拟机11】线程上下文类加载器

    前言 目前学习到的类加载的知识,都是基于[双亲委托机制]的.那么JDK难道就没有提供一种打破双亲委托机制的类加载机制吗? 答案是否定的. JDK为我们提供了一种打破双亲委托模型的机制:线程上下文类加载 ...

  9. springcloud(二) 微服务架构编码构建

    微服务架构编码构建 1 基础知识 1.1 版本 2 微服务cloud整体聚合父工程Project 2.1 new project 2.2 字符编码设置 utf-8 2.3 pom.xml 2.4 父工 ...

  10. Java:多线程计数

    Java:多线程计数 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 1. CountDownLatch 概念 让一些线程阻塞直到另一些线程完成一系列操作才被唤醒 ...