20200321上记笔记

本周重点是队列和栈的入门,队列只能从队首出队,队尾入队;而栈只能从栈顶进行入栈和出栈;

1 移动圆盘 (100分)

给出n个圆盘的半径,现在要把这些圆盘依次放在柱子上,当准备把第i个半径为ai的圆盘放置到柱子上时,如果柱子顶部的圆盘半径小于ai,那么将柱子顶部的圆盘拿出,如果顶部的盘子半径仍然小于ai,那么继续拿出,直到顶部圆盘半径大于或等于ai为止,此时才把第i个盘子放到柱子上。那么,最后从下往上输出柱子上的圆盘半径依次是什么?

输入格式:
第一行包含一个整数n(n<=100000),表示有n个圆盘要依次放到柱子上。 接下来n行,每行一个整数,表示第i个圆盘的半径ai (ai<=100000)。

输出格式:
输出多行,表示最后柱子上中的圆盘半径。

输入样例:

5
5
3
2
4
1

输出样例:

5
4
1

#include<stdio.h>
#include<stdlib.h>
int a[100007],b[100007];
int main(){
	int top=0;
	int n;
	int i,j=1,k;
	//入栈
	scanf("%d",&n);
	for (i=0;i<n;i++){
		scanf("%d",&b[i]);
	}
	a[0]=b[0];
	i=1;
	for (j=1;j<n;j++,i++){
		if (b[j]<=a[i-1]){
			a[i]=b[j];continue;
		}
		while(b[j]>a[i-1]){
			a[i-1]=0;i--;
			if (i==0) break;
		}
		if (i==0){
			a[i]=b[j];continue;
		}
		a[i]=b[j];
	}
	if (a[0]==0) printf("%d",a[0]);
	for (i=0;i<n;i++){
		if (a[i]==0) break;/*因为圆盘的半径不可能等于0,若等于0,则只能是被删除或不曾使用过的(其中数组为全局变量,不曾使用的初始值为0);*/
		printf("%d\n",a[i]);
	}
	return 0;
}

2 微信号 (100分)

小明刚认识了新同学小红,他想要小红的微信号,小红不想直接告诉他,所以给了小明一串加密了的数字,并且把解密规则告诉了小明。

解密规则是:首先删除第1个数,接着把第2个数放在这串数的最后面,再删除第3个数,并把第4个数放在这串数的最后面……直至只剩最后一个数,把最后一个数也删除。

按照删除的顺序,把这些数字连在一起就是小红的微信号。请你按照解密规则帮小明得到小红的微信号。

输入格式:
第一行包括一个正整数n(1 < n < 500),表示这串微信号的长度;

第二行包括n个数字,即加密的小红的微信号。

输出格式:
输出解密后的微信号,相邻数字之间有空格。

输入样例:

9
1 2 3 4 5 6 7 8 9

输出样例:

1 3 5 7 9 4 8 6 2

#include<stdio.h>
#include<stdlib.h>
int a[5007],b[5007];
int main(){
	int n;
	int i,j=1,k;
	scanf("%d",&n);
	int head=1,rear=n; 
	for (i=1;i<=n;i++){
		scanf("%d",&a[i]);
	} 
	for (head=1;head<=rear;head++){
		b[j]=a[head];//数组b用来存放删除的数据
		head++;
		a[++rear]=a[head];//将数据移到这串数的最后面
		j++;
	}
	for (k=1;k<=n;k++){
		printf("%d ",b[k]);
	}
	return 0;
} 

3 糖果 (100分)

学校里有n个孩子,从1到n对这些孩子进行编号。老师将给孩子们分发糖果,第i个孩子希望至少获得ai个糖果。

老师要求孩子们排队。 最初,第i个孩子站在队伍的第i个位置。 然后,老师开始分发糖果。分发糖果的规则是:将m个糖果给队伍中的第一个孩子,如果这个孩子没有得到足够的糖果,那么这个孩子会走到队伍的尽头;否则这个孩子就回家了。当队伍不为空时,重复这个规则一直分发糖果。 如果考虑所有孩子回家的顺序。老师想知道,哪个孩子将是这个顺序中的最后一个?

输入格式:
第一行包含两个整数n,m(1≤n≤100; 1≤m≤100)。 第二行包含n个整数a1,a2,...,an(1≤ai≤100)。

输出格式:
输出一个整数,代表最后一个孩子的编号。

输入样例:
在这里给出一组输入。例如:

3 3
2 4 3

输出样例:
在这里给出相应的输出。例如:

2

#include<stdio.h>
#include<stdlib.h>
int a[10000007],sum[1000007];
int main(){
	int n,m;
	int b[1000007];
	int i,j=0,k;
	scanf("%d %d",&n,&m);
	for (i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	for (k=1;k<=n;k++){
		b[k]=k;//存放编号
	}
	int head=1,rear=n;
	for (head=1;head<=rear;head++){
		sum[head]+=m;
		if (sum[head]>=a[head]){
			continue;
		} 
		b[++rear]=b[head];
		a[rear]=a[head];
		sum[rear]=sum[head];
	}
	printf("%d",b[rear]);
	return 0;
} 

4 谁比我大 (100分)

给定一个含有n个整数的数列a1,a2,...an。定义函数 f(ai)表示数列中第i个元素ai之后第一个大于ai的元素的下标,若这样的元素不存在,则f(ai)=0。

输入格式:
第一行包含一个正整数n(n<=1e6);

第二行包含n个正整数 a1,a2,...an(1<=ai<=1e9)。

输出格式:
输出仅一行包含 n个整数,分别代表 f(ai) 的值。

输入样例:

5
1 4 2 3 5

输出样例:

2 5 4 5 0

#include<stdio.h>
#include<stdlib.h>
int a[1000007];
int i,j,k;
int n;
int f(int m){
	int temp=0;
	for (k=i+1;k<=n;k++){
		if (a[k]>m){
			temp=k;break;
		}
	} 
	return temp;
}
int main(){
	scanf("%d",&n);
	for (i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	for (i=1;i<=n;i++){
		j=f(a[i]);
		printf("%d ",j);
	}
	return 0;/*此题更好的做法是单调栈,我的做法暴力求解,不是太好,而且好像在洛谷一题差不多的要用单调栈才能过,但这个能过PTA*/
}

5 后缀表达式 (100分)

这题很经典,原理的话参考这篇博客 作者讲得很清楚

所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右进行(不用考虑运算符的优先级)。

如:中缀表达式 3(5–2)+7 对应的后缀表达式为:352-7+ 。

请将给出的中缀表达式转化为后缀表达式并输出。

输入格式:
输入仅一行为中缀表达式,式中所有数字均为个位数,表达式长度小于1000。

输出格式:
输出一行,为后缀表达式,式中无空格。

输入样例:

2+48+(88+1)/3

输出样例:

248+881+3/+

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#include<math.h>
#include<time.h>
#define ll long long
#define MAX 1000007
#define Max(a,b)((a)>(b)?a:b)
#define Min(a,b)((a)>(b)?b:a)
int pr(char op) {                
    int di;
    if (op=='*'||op =='/')di=2;
    if (op=='+'||op=='-')di=1;
    if (op=='(')di=0;
    return di;
}
char a[MAX],b[MAX];
int main(){
	int i,j,k,l,m=0,n; 
	scanf("%s",a);
	l=strlen(a);
	for(i=0;i<l;i++){
		if(isdigit(a[i]))printf("%c",a[i]);
		else{
			if(m==0)b[++m]=a[i];
			else if(a[i]=='(')b[++m]=a[i];
			else if(a[i]==')'){
				while(b[m]!='('){
					printf("%c",b[m]);
					m--;
				} m--;
			}
			else {
				while(pr(a[i])<=pr(b[m])){
					printf("%c",b[m]);
					m--;
					if(m==0)break;
				}
				b[++m]=a[i];
			} 
		}
	}
	while(m!=0){
		printf("%c",b[m]);
		m--;
	}
	return 0;
}

6 后缀表达式计算 (100分)

这题也很经典,原理的话参考这篇博客 作者说的很清楚
类似的题目P1449 后缀表达式

Kunkun学长觉得应该让学弟学妹了解一下这个知识点:后缀表达式相对于中缀表达式更容易让计算机理解和学习。现在kunkun学长给出一串后缀表达式,你能帮他算出这个后缀表达式的值吗?

输入格式:
第一行输入后缀表达式长度n(1<=n<=25000);

第二行输入一个字符串表示后缀表达式(每个数据或者符号之间用逗号隔开,保证输入的后缀表达式合法,每个数包括中间结果保证不超过long long长整型范围)

输出格式:
输出一个整数,即后缀表达式的值。

输入样例1:

6
10,2,+

输出样例1:

12

输入样例2:

14
2,10,2,+,6,/,-

输出样例2:

0

#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <stack>
using namespace std;
stack<long long> a;
long long now,real[25007];
char num[25007];
int main(){
	int n;
	cin>>n;
	int i,j=0,flag=0;
	for (i=0;i<n;i++){
		cin>>num[i];
	}
	for (i=0;i<n;i++){
		if (num[i]>='0'&&num[i]<='9'){
			now*=10;now+=num[i]-'0';
		}
		else if((num[i]==',')){
			if (num[i-1]>='0'&&num[i-1]<='9'){
				if (flag==0){
					real[++j]=now;
				}
				else {
					real[++j]=now*(-1);
				}
				now=0;flag=0;
			}
			else if(num[i-1]=='+'){
				real[j-1]=real[j]+real[j-1];
				real[j]=0;
				j--;
			}
			else if(num[i-1]=='-'){
				real[j-1]=real[j-1]-real[j];
				real[j]=0;
				j--;
			}
			else if(num[i-1]=='*'){
				real[j-1]=real[j-1]*real[j];
				real[j]=0;
				j--;
			}
			else if(num[i-1]=='/'){
				real[j-1]=real[j-1]/real[j];
				real[j]=0;
				j--;
			}
		}
		else {
			if (i<n-1){
				if(num[i]=='-'){
					if (num[i+1]!=',')flag=1;
				}
				continue;
			}
			else {
				if(num[i]=='+'){
					real[j-1]=real[j]+real[j-1];
					real[j]=0;
					j--;
				}
				else if(num[i]=='-'){
					real[j-1]=real[j-1]-real[j];
					real[j]=0;
					j--;
				}
				else if(num[i]=='*'){
					real[j-1]=real[j-1]*real[j];
					real[j]=0;
					j--;
				}
				else if(num[i]=='/'){
					real[j-1]=real[j-1]/real[j];
					real[j]=0;
					j--;
				}
			}
		}
	}
	cout<<real[1]<<endl;
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/xiao-qingjiang/p/12581455.html