第六周PTA笔记 括号匹配调整+堆放石子+最大积分+168
括号匹配调整
如果通过插入“ +”和“ 1”可以从中得到格式正确的数学表达式,则将带括号的序列称为正确的。
例如,序列 "(())()","()"和 "(()(()))"是正确的,而")(","(()))("和"(()" 不是。
定义重新排序操作:选择括号序列的任意连续子段(子字符串),然后以任意方式对其中的所有字符进行重新排序。
当重新排序的子段的长度为t时,重新排序操作需要耗时t秒。
例如,对于“))((”,他可以选择子字符串“)(”并重新排序“)()(”(此操作将花费2秒)。
不难看出,重新排序操作不会改变左括号和右括号的数量。
现在,LD想花费最少的时间,通过任意次数(可能为零)执行重新排序操作来使括号序列变成正确的。
输入格式:
第一行包含一个整数n(1≤n≤1e6),表示序列的长度;
第二行包含一个长度为n的字符串,仅由字符‘(’和‘)’组成。
输出格式:
输出一个整数,表示使括号序列正确的最小秒数;如果不可能实现,则输出-1。
输入样例:
8
))((())(
输出样例:
6
思路:参考了网络上的一篇博客pta括号匹配调整(栈)。了解了一下思路后我是用数组来做的,对于本人来说比较好理解。进行完是否可以实现括号正确序列的判断后,再进行秒数多少的计算。要使秒数最短,就要使重新排序的字符串最短。当遇到'('和')'时,这时不需要交换;遇到')'和'('时,可以将其作为子字符串进行重新排序;若是除了这两种之外的情况,就是将字符存进另一个数组后,再进行判断,或者与已存入另一个数组的字符进行比较判断。
#include<stdio.h>
char s[1000000],a[1000000];
int main()
{
int n,i,flag=0,t=0;
scanf("%d %s",&n,s);
if(n%2!=0){
printf("-1");
return 0;
}//若输入的括号数为奇数则肯定不能实现括号序列正确
else{
for(i=0;i<n;i++)
{
if(s[i]=='(')flag++;
}
if(flag!=n/2){
printf("-1");
return 0;
}//若左右括号的数不相等,则也不能实现括号序列正确
}
flag=0;
for(i=0;i<n;i++)
{
if(a[flag]!=0){
if(a[flag]=='('&&s[i]==')')flag--;
else if(a[flag]==')'&&s[i]=='('){
t+=2;
flag--;
}
else{
flag++;
a[flag]=s[i];
}
}
else a[flag]=s[i];
}
printf("%d",t);
return 0;
}
堆放石子
有N堆石子,每堆石子有若干石头,所有石头的总数是N的倍数。
可以在任意一堆上取若干石头,进行移动。移动规则是:在第一堆上取的石子,只能移到第二堆;在第N堆上取的石子,只能移到N-1堆;其他堆上取的,可以移到相邻左边或者右边。如何用最少的移动次数使得每堆石子的数量一样多呢?
当N=4时,4堆石子数为:9、8、17、6
移动3次可以使4堆数目一样多:
从第3堆取4个石子放到第4堆(9、8、13、10)
从第3堆取3个放到第2堆(9、11、10、10)
从第2堆取1个放到第1堆(10、10、10、10)
输入格式:
第一行包含一个整数N(1<= N <=100),表示有N堆石子;
接着有N行,每行一个整数ai(1<= ai <=10000),表示第i堆石子的数量。
输出格式:
输出一个整数,表示使所有石子堆的石子均达到相等时需要的最少移动次数。
输入样例:
4
9 8 17 6
输出样例:
3
思路:参考了7-4堆放石子。这道题个人感觉很像均等这题,于是我一开始完全是用均等那道题的思路去做的。但其实这道题比我所提到的那题要简单一些(尽管我一点儿思路都没有)。不能左边右边都去想,这样会很乱,就是只想往左边搬石子,搬的个数用另一个数组来储存,要是该数为0,则不用搬运,要是为正就是往左搬,要是为负就是往右搬。
#include<stdio.h>
int b[105];
int main()
{
int a[105],N,i,s=0,ave,t=0;
scanf("%d",&N);
for(i=0;i<N;i++)
{
scanf("%d",&a[i]);
s+=a[i];
}
ave=s/N;
for(i=1;i<N;i++)
{
b[i]=ave-a[i-1]+b[i-1];
}
for(i=0;i<N;i++)
{
if(b[i]!=0)t++;
}
printf("%d",t);
return 0;
}
最大积分
给你一罐颜料,并规定写出1-9每个数字所用的颜料是指定量的,当你用这罐颜料写下的数字越大,你得到的积分越多。
那么,你能得到的最大积分是多少呢?
输入格式:
第一行包含一个整数n(0≤n≤1000),表示给定颜料量。
第二行包含九个正整数a1,a2,… ,a9,分别表示写下数字1-9所需要的颜料量。
输出格式
输出一个数,表示你能得到的最大积分;如果颜料连一个数字都不够写,那么输出-1。
输入样例:
2
9 11 1 12 5 8 9 10 6
输出样例:
33
思路1(仅供参考,有瑕疵):在判断了是否能写数字后,若可以,将每个数字所需的颜料进行比较,选择需要颜料少的,若两个数字需要的颜料一样,则选择数字大的,这个思路有两个点没过。
自己测了一下数据,例如这组
523
174 175 176 173 172 171 174 175 177
按照我的程序将会输出877,但正确答案是986,这是因为我的代码只考虑了局部,忽略了整体。
//瑕疵代码
#include<stdio.h>
#include<stdlib.h>
int cmp(const void*c,const void*d);
int a[10],b[100000];
int main()
{
int n,i,max,t=0,x;
scanf("%d",&n);
for(i=0;i<9;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<9;i++)
{
if(n/a[i]>0)break;
}
if(i==9||n==0){
printf("-1");
return 0;
}
max=n/a[0];
b[t]=1;
while(n>0){
for(i=1;i<9;i++)
{
if(max<=n/a[i]){
max=n/a[i];
b[t]=i+1;
}
}
if(n>=a[b[t]-1])n-=a[b[t]-1];
else break;
t++;
max=n/a[0];
b[t]=1;
}//这部分需要改进
qsort(b,t,sizeof(int),cmp);
for(i=0;i<t;i++)
{
printf("%d",b[i]);
}
return 0;
}
int cmp(const void*c,const void*d)
{
return *(int*)d-*(int*)c;
}
思路2:参考了7-6最大积分。在此总结一下思路,首先将9个数字中所需要最少颜料找出来,通过这个确定位数,因为一个数字的大小首先是位数,其次是最高位数字,接着依次往下推。关键步骤在代码中将会标注。
//正确代码
#include<stdio.h>
#include<stdlib.h>
int cmp(const void*c,const void*d);
int a[10],b[100000];
int main()
{
int n,i,min,t=0,x,r;
min=1000000;
scanf("%d",&n);
for(i=0;i<9;i++)
{
scanf("%d",&a[i]);
if(min>a[i])min=a[i];
}
if(n/min==0){
printf("-1");
return 0;
}
x=n/min;
while(x!=0){
r=n-(x-1)*min;
for(i=8;i>=0;i--)
{
if(a[i]<=r){
b[t]=i+1;
break;
}
}
n-=a[b[t]-1];
t++;
x--;
}//关键步骤
qsort(b,t,sizeof(int),cmp);
for(i=0;i<t;i++)
{
printf("%d",b[i]);
}
return 0;
}
int cmp(const void*c,const void*d)
{
return *(int*)d-*(int*)c;
}
168
汉堡包在大街上大摇大摆的走着,看着手机上一道难倒数万人的小学数学题:
1 + 1 = 0
1 + 6 = 1
6 + 6 = 2
8 + 1 = 2
8 + 6 = 3
汉堡包看完之后发现上面这些加法的答案就是看1,6,8中圈圈的个数嘛!
突然之间,所有大厦上的LED屏幕上的广告全部变成数字1,6,8三个数字的随机闪现。
现给你一块n*m的LED屏幕,上面有且仅有一个数字(1,6,or 8),请你输出你看见的那个字母。
输入格式:
第一行输入两个整数n,m(2<= m, n <= 1000);
接下来n行,每行由m个数字0和1组成,其中1表示数字1,6,8的组成部分。
输出格式:
输出一个整数,代表图形表示的数字。
输入样例:
7 7
0 0 0 0 0 0 0
0 0 1 1 1 0 0
0 0 1 0 1 0 0
0 0 1 1 1 0 0
0 0 1 0 1 0 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
输出样例:
8
思路1(有bug):通过在1中遍历到0的第一行来判断(先确定一个以1为边界的范围),如果改行的末尾是1,则输出8,若是0,则输出6。若没有0,那就是1了。但是这样做导致了一个点出错,我想应该是这种情况导致的。但如果没有这种情况,我觉得我对于这题的思路还算是清晰,哈哈哈哈哈哈哈哈哈哈哈哈
后来经过询问,发现一直没有过的那个点可能是这个亚子的。
7 7
0 0 0 0 0 0 0
0 0 1 1 1 1 1
0 0 1 1 0 0 0
0 0 1 1 1 1 1
0 0 1 1 0 0 0
0 0 1 1 1 1 1
0 0 0 0 0 0 0
该数据输出为8,是没有边界的,而我的方法将会把上面的数据判断为6。
//瑕疵代码,仅供参考
#include<stdio.h>
char s[1005][1005];
int main()
{
int n,m,i,j,x1,x2,y1,y2,x;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf(" %c",&s[i][j]);
}
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(s[i][j]=='1'){
x=j;
x1=i;
y1=j;
while(s[i][j]=='1'){
j++;
}
y2=j;
j=x;
while(s[i][j]=='1'){
i++;
}
x2=i;
i=n;
break;
}
}
}//确定关于1的范围的部分
for(i=x1;i<x2;i++)
{
for(j=y1+1;j<y2;j++)
{
if(s[i][j]=='0'){
if(s[i][y2-1]=='1'){
printf("8");
return 0;
}
else{
printf("6");
return 0;
}
}
}
}//判断部分
printf("1");
return 0;
}
思路2:由于自己的方法不可行,于是琢磨了一下朋友的思路。通过判断每一行1的个数的种类来判断该数为什么。例如,对于8,总共有两种1,就像题目当中一种是三个1,还有一种是两个1。总结规律可得,对于数字1只有一种1;数字6有三种1;数字8有两种1。在这位同学的博客里有图示。
我是通过从第一行到最后一行遍历来判断1的种数,因为没有采取之前左上角和右下角确定1的范围的方法,因为可能会出现这种情况。
7 7
0 0 0 0 0 0 0
0 0 1 1 1 0 0
0 0 1 0 1 0 0
0 0 1 1 1 1 0
0 0 1 0 0 1 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
//正确代码
#include<stdio.h>
char s[1005][1005];
int a[1005];
int main()
{
int n,m,i,j,t=0,flag=0;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf(" %c",&s[i][j]);
}
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(s[i][j]=='1')t++;
}
if(a[t]==0&&t>0){
a[t]=1;
flag++;
}
t=0;
}
if(flag==1)printf("1");
else if(flag==2)printf("8");
else printf("6");
return 0;
}
经过这次的做题,我再一次感觉自己真的是菜死了。/(ㄒoㄒ)/~~
第六周PTA笔记 括号匹配调整+堆放石子+最大积分+168的更多相关文章
- 《Linux内核设计与分析》第六周读书笔记——第三章
<Linux内核设计与实现>第六周读书笔记——第三章 20135301张忻估算学习时间:共2.5小时读书:2.0代码:0作业:0博客:0.5实际学习时间:共3.0小时读书:2.0代码:0作 ...
- 《Linux内核分析》第六周学习笔记
<Linux内核分析>第六周学习笔记 进程的描述和创建 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/co ...
- Linux内核分析第六周学习笔记——分析Linux内核创建一个新进程的过程
Linux内核分析第六周学习笔记--分析Linux内核创建一个新进程的过程 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...
- linux内核分析第六周学习笔记
LINUX内核分析第六周学习总结 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.c ...
- 20165326 java第六周学习笔记
第六周学习总结 ch8 String类对于有效处理字符序列信息非常重要. String对象的字符序列不能被修改删除,无法发生变化. StringBuffer类的对象实体的内存空间可以自动改变大小,便于 ...
- Linux内核分析——第六周学习笔记20135308
第六周 进程的描述和进程的创建 一.进程描述符task_struct数据结构 1.操作系统三大功能 进程管理 内存管理 文件系统 2.进程控制块PCB——task_struct 也叫进程描述符,为了管 ...
- 软件测试第六周学习笔记之“Win8 APP应用程序的白盒测试”
这周的学习笔记我想写点自己关于实验中碰到的问题和感想. 因为这次做的是白盒测试,所以我决定去测试一下上回测试的app的功能函数. 这次我用的是单元测试项目来做的白盒测试: 创建单元测试的步骤: 1.点 ...
- 第五周PTA笔记 后缀表达式+后缀表达式计算
后缀表达式 所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右进行(不用考虑运算符的优先级). 如:中缀表达式 3(5–2 ...
- 第六周PTA作业
第一题: #include<stdio.h> int main () { float a,b; scanf("%f %f\n",&a,&b); floa ...
随机推荐
- CF666E-Forensic Examination【广义SAM,线段树合并】
正题 题目链接:https://www.luogu.com.cn/problem/CF666E 解题思路 给出一个串\(S\)和\(n\)个串\(T_i\).\(m\)次询问\(S_{a\sim b} ...
- docker-compose 搭建kafka集群
docker-compose搭建kafka集群 下载镜像 1.wurstmeister/zookeeper 2.wurstmeister/kafka 3.sheepkiller/kafka-manag ...
- 密码学系列之:加密货币中的scrypt算法
目录 简介 scrypt算法 scrypt算法详解 scrypt的使用 简介 为了抵御密码破解,科学家们想出了很多种方法,比如对密码进行混淆加盐操作,对密码进行模式变换和组合.但是这些算法逐渐被一些特 ...
- Apache ShardingSphere:由开源驱动的分布式数据库中间件生态
2021 年 7 月 21 日 2021 亚马逊云科技中国峰会现场,SphereEx 联合创始人.Apache ShardingSphere PMC 潘娟受邀参与此次峰会,以<Apache Sh ...
- 题解 [HAOI2016]字符合并
题目传送门 Description 有一个长度为 \(n\) 的 \(01\) 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数. 得到的新字符和分数由这 k 个字符确定.你需要 ...
- 洛谷4072 SDOI2016征途 (斜率优化+dp)
首先根据题目中给的要求,推一下方差的柿子. \[v\times m^2 = m\times \sum x^2 - 2 \times sum \times sum +sum*sum \] 所以\(ans ...
- Android QMUI实战:实现APP换肤功能,并自动适配手机深色模式
Android换肤功能已不是什么新鲜事了,市面上有很多第三方的换肤库和实现方案. 之所以选择腾讯的QMUI库来演示APP的换肤功能,主要原因: 1.换肤功能的实现过程较简单.容易理解: 2.能轻松适配 ...
- Java(31)泛型和可变参数
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228443.html 博客主页:https://www.cnblogs.com/testero ...
- UltraSoft - Beta - Scrum Meeting 9
Date: May 25th, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 记录Scrum Meeting Liuzh 前端 用户忘记密码界面初稿完成 Kkk ...
- spring cloud feign的基本使用
在上一节,我们学会了如何使用ribbon进行来进行服务之间的调用,但是那种需要通过RestTemplate来进行调用而且当参数比较多时,使用起来就比较麻烦.那么有没有一种调用远程方法(别的服务)就像调 ...