CCF模拟题闲时小练(12基础题类)

这篇博客介绍了如何使用数据结构栈解决中缀表达式转后缀表达式的问题,结合实例阐述了计算二十四点游戏的方法。接着,博主通过两个与交通灯相关的问题——小明上学和放学,展示了如何处理红绿灯信号的计算,以确定通行时间。文章以实际题目为例,解释了解题思路和关键点。
摘要由CSDN通过智能技术生成

1.小中大

在这里插入图片描述

import java.util.Scanner;
public class Main{
public static void main(String[] args) {
	Scanner scan = new Scanner(System.in);
    int n=scan.nextInt();
    int i,max,min;
    double mid;
 	int[] arr = new int[n];
 	for(i=0;i<n;i++){
  		arr[i]=scan.nextInt();
  	}
   max=arr[0];
   min=arr[0];
   for(i=0;i<n;i++){
   	if(arr[i]>max)
   	max=arr[i];
  	if(arr[i]<min)
   	min=arr[i];
  }
  System.out.print(max);
  System.out.print(" ");
  if(n%2==0){
  	mid=(arr[arr.length/2]+arr[(arr.length-2)/2])/(2.0);
	  if((arr[arr.length/2]+arr[(arr.length-2)/2])%2==0) {
		  System.out.print((int)mid);
		  System.out.print(" ");
	  }else {
		  System.out.print(mid);
		  System.out.print(" ");
	  }
  }else{
	  mid=arr[arr.length/2];
	  System.out.print((int)mid);
	  System.out.print(" ");
  }
  System.out.print(min);
  System.out.print(" ");
 }
}

2.二十四点

在这里插入图片描述

其实就是四则运算,用到了数据结构栈的知识来解决
思路是:中缀表达式转后缀表达式(需要定义一个操作符栈),再对后缀表达式进行计算(需要定义一个操作数栈)

转换规则
中缀转后缀:
1.数字直接输出成为后缀表达式的一部分
2.非数字,若栈内空则压栈
3.当前输入的操作符比栈顶元素的优先则压栈
4.不优先(包含等于)则顶部元素一直出栈,直到栈顶元素比当前元素优先才停止出栈,若是右括号,则出栈遇到左括号停止,括号成对消失
对后缀表达式计算:
1.遇到数字则压栈
2.遇到符号则弹栈,弹两次,分别作为右操作数和左操作数,并将计算的结果压栈

import java.util.*;

public class Main{
	
	public static void main(String[] args) {
		Stack<Character> priStack = new Stack<Character>();// 操作符栈      
	       
		Scanner scan = new Scanner(System.in);
        int n=scan.nextInt();
        int i,k;
        String buf=new String();//输出的后缀表达式
        String temp=new String();//用于暂存输入的中缀表达式
        String[] arr = new String[n];//字符串数组,用于存放转化后的后缀表达式
        //中缀表达式转化为后缀表达式
        //数字直接输出->
        //非数字,栈内空压栈->
        //当前输入的操作符比栈顶元素的优先则压栈->
        //不优先(包含等于)则顶部元素一直出栈,直到栈顶元素比当前元素优先才停止出栈
        for(i=0;i<n;i++) {
        	temp=scan.next();
        	buf="";
        	char d;
        	for(k=0;k<7;k++) {
        		 char ch=temp.charAt(k);
        		 if(ch>='1'&&ch<='9') {
        			 buf=buf+ch;
        		 }else if (priStack.empty()==true) {
        			 priStack.push(ch);
        		 }else if(getprio(ch)<getprio(d=(priStack.peek()))) {
        			 priStack.push(ch);
        		 }else {
        			 while(priStack.empty()==false) {
        				 if(getprio(priStack.peek())<=getprio(ch)) {
        					 buf+=priStack.peek();
        				 	 priStack.pop();
        				 }
        				 else 
        					 break;
        			 }
        			 priStack.push(ch);
        		 }
        	}
        	 while(priStack.empty()==false) {
				 buf+=priStack.pop();
			 }
        	 arr[i]=buf;
        }
        for(i=0;i<n;i++) {
        	if(caculate(arr[i])==24) {
        		System.out.println("Yes");
        	}else {
        		System.out.println("No");
        	}
        	//System.out.println(arr[i]);//打印后缀表达式看看正确与否
        	//System.out.println(caculate(arr[i]));//计算结果
        }
        
      
	}
	//根据算数符号获取优先级
	public static int getprio(char oper) {
		if(oper=='+'||oper=='-') {
			return 1;
		}else {
			return 0;
		}
	}
	//后缀表达式计算
	public static int caculate(String str) {  
		int j;	
		int left,right,result;
		Stack<Integer> numStack = new Stack<Integer>();// 操作数栈   
		for(j=0;j<7;j++) {
	   		 char ch=str.charAt(j);
	   		 if(ch>='0'&&ch<='9') {
	   			 numStack.push(ch-'0');
	   		 }else {
	   			right=numStack.pop();
	   		    left=numStack.pop();
		   		switch(ch) {
		   				case '+':numStack.push(left+right);break;
		   				case '-':numStack.push(left-right);break;
		   				case 'x':numStack.push(left*right);break;
		   				case '/':numStack.push(left/right);break;
		   		}
	   			
	   		 }
	   	}
	   	result=numStack.pop();
	    return result;
	}
}

3.小明上学

题目背景

小明是汉东省政法大学附属中学的一名学生,他每天都要骑自行车往返于家和学校。为了能尽可能充足地睡眠,他希望能够预计自己上学所需要的时间。他上学需要经过数段道路,相邻两段道路之间设有至多一盏红绿灯。
  京州市的红绿灯是这样工作的:每盏红绿灯有红、黄、绿三盏灯和一个能够显示倒计时的显示牌。假设红绿灯被设定为红灯 r 秒,黄灯 y 秒,绿灯 g 秒,那么从 0 时刻起,[0,r) 秒内亮红灯,车辆不许通过;[r, r+g) 秒内亮绿灯,车辆允许通过;[r+g, r+g+y) 秒内亮黄灯,车辆不许通过,然后依次循环。倒计时的显示牌上显示的数字 l(l > 0)是指距离下一次信号灯变化的秒数。
问题描述

一次上学的路上,小明记录下了经过每段路的时间,和各个红绿灯在小明到达路口时的颜色和倒计时秒数。希望你帮忙计算此次小明上学所用的时间。
输入格式
  输入的第一行包含空格分隔的三个正整数 r、y、g,表示红绿灯的设置。这三个数均不超过 106。
  输入的第二行包含一个正整数 n(n ≤ 100),表示小明总共经过的道路段数和看到的红绿灯数目。
  接下来的 n 行,每行包含空格分隔的两个整数 k、t。k=0 表示经过了一段道路,耗时 t 秒,此处 t 不超过 106;k=1、2、3 时,分别表示看到了一个红灯、黄灯、绿灯,且倒计时显示牌上显示的数字是 t,此处 t 分别不会超过 r、y、g。
输出格式

输出一个数字,表示此次小明上学所用的时间。
  
样例输入
30 3 30
8
0 10
1 5
0 11
2 2
0 6
0 3
3 10
0 3
样例输出

70

样例说明

小明先经过第一段道路,用时 10 秒,然后等待 5 秒的红灯,再经过第二段道路,用时 11 秒,然后等待 2 秒的黄灯和 30 秒的红灯,再经过第三段、第四段道路,分别用时6、3秒,然后通过绿灯,再经过最后一段道路,用时 3 秒。共计 10 + 5 + 11 + 2 + 30 + 6 + 3 + 3=70 秒。
  
评测用例规模与约定
  测试点 1, 2 中不存在任何信号灯。
  测试点 3, 4 中所有的信号灯在被观察时均为绿灯。
  测试点 5, 6 中所有的信号灯在被观察时均为红灯。
  测试点 7, 8 中所有的信号灯在被观察时均为黄灯。
  测试点 9, 10 中将出现各种可能的情况。

这题就一个陷阱,等完黄灯还要等红灯


import java.util.*;

public class Main{
	
	public static void main(String[] args) {
	    Scanner scan = new Scanner(System.in);
        int r=scan.nextInt();
        int y=scan.nextInt();
        int g=scan.nextInt();
        int n=scan.nextInt();
        int sum=0;
        for(int i=0;i<n;i++) {
        	int k=scan.nextInt();
        	int t=scan.nextInt();
        	switch (k) {
	        	case 0:
	        	case 1:sum=sum+t;break;
	        	case 2:sum=sum+t+r;break;
	        	case 3:
        	}
        }
        System.out.println(sum);
	}
}

4.小明放学

题目背景

汉东省政法大学附属中学所在的光明区最近实施了名为“智慧光明”的智慧城市项目。具体到交通领域,通过“智慧光明”终端,可以看到光明区所有红绿灯此时此刻的状态。小明的学校也安装了“智慧光明”终端,小明想利用这个终端给出的信息,估算自己放学回到家的时间。
问题描述
  一次放学的时候,小明已经规划好了自己回家的路线,并且能够预测经过各个路段的时间。同时,小明通过学校里安装的“智慧光明”终端,看到了出发时刻路上经过的所有红绿灯的指示状态。请帮忙计算小明此次回家所需要的时间。
输入格式

输入的第一行包含空格分隔的三个正整数 r、y、g,表示红绿灯的设置。这三个数均不超过 106。
  输入的第二行包含一个正整数 n,表示小明总共经过的道路段数和路过的红绿灯数目。
  接下来的 n 行,每行包含空格分隔的两个整数 k、t。k=0 表示经过了一段道路,将会耗时 t 秒,此处 t 不超过 106;k=1、2、3 时,分别表示出发时刻,此处的红绿灯状态是红灯、黄灯、绿灯,且倒计时显示牌上显示的数字是 t,此处 t 分别不会超过 r、y、g。
输出格式

输出一个数字,表示此次小明放学回家所用的时间。

样例输入

30 3 30
8
0 10
1 5
0 11
2 2
0 6
0 3
3 10
0 3
样例输出

46
样例说明

小明先经过第一段路,用时 10 秒。第一盏红绿灯出发时是红灯,还剩 5 秒;小明到达路口时,这个红绿灯已经变为绿灯,不用等待直接通过。接下来经过第二段路,用时 11 秒。第二盏红绿灯出发时是黄灯,还剩两秒;小明到达路口时,这个红绿灯已经变为红灯,还剩 11 秒。接下来经过第三、第四段路,用时 9 秒。第三盏红绿灯出发时是绿灯,还剩 10 秒;小明到达路口时,这个红绿灯已经变为红灯,还剩两秒。接下来经过最后一段路,用时 3 秒。共计 10+11+11+9+2+3 = 46 秒。
评测用例规模与约定
  有些测试点具有特殊的性质:
  * 前 2 个测试点中不存在任何信号灯。
  测试点的输入数据规模:
  * 前 6 个测试点保证 n ≤ 103。
  * 所有测试点保证 n ≤ 105。

主要思路参考这个:
例如:红灯15秒,绿灯20秒,黄灯10秒。在我们出发时有一个灯,是还剩10秒的红灯,在经过一段50秒的平路后到达这个红灯。首先,根据我上面定义的周期,这个红灯已经持续了15-10=5秒,然后50秒后到达这个红灯,此时这个灯已经花费了50+5=55秒。那么这个55就是从初始状态到小明到达这个灯时它所花费的时间,现在要确定这个灯的状态和所剩时间,用55取余一个周期的时间,即55%(15+20+10)=10。即到达这个灯时它的状态是还剩15-10=5秒的红灯。


import java.util.*;

public class Main{
	
	public static void main(String[] args) {
	
	    Scanner scan = new Scanner(System.in);
        long r=scan.nextInt();
        long y=scan.nextInt();
        long g=scan.nextInt();
        int n=scan.nextInt();
        long sum=0;
        //long T=0;
        for(int i=0;i<n;i++) {
        	int k=scan.nextInt();
        	long t=scan.nextInt();
        	long temp;
        	switch (k) {
        	    //道路
	        	case 0:sum=sum+t;break;
	        	//红灯
	        	case 1:{
	        	
	        			temp=(r-t+sum)%(r+y+g);
	        			if(temp>=0&&temp<r) 
	        				sum=sum+r-temp;
	        			else if(temp>=r+g&&temp<r+g+y) {
	        				sum=sum+r+g+y-temp+r;
	        			}
	        			break;
	        			
	        	}
	        	//黄灯	
	        	case 2:{
	        		temp=(y-t+sum)%(r+y+g);
        			if(temp>=0&&temp<y) 
        				sum=sum+y-temp+r;
        			else if(temp>=y&&temp<r+y) {
        				sum=sum+r+y-temp;
        			}
        			break;
	        	}
	        	//绿灯
	        	case 3:{
	        		temp=(g-t+sum)%(r+y+g);
        			if(temp>=g&&temp<g+y) 
        				sum=sum+y+g-temp+r;
        			else if(temp>g+y&&temp<=r+y+g) {
        				sum=sum+r+y+g-temp;
        			}
        			break;
	        	}
        	}
        }
        System.out.println(sum);
	}
	    
}

5.卖菜

在这里插入图片描述


import java.util.*;

public class Main{
	
	public static void main(String[] args) {
	
	    Scanner scan = new Scanner(System.in);
        int n=scan.nextInt();
        int i;
        int []arr=new int[n];
        int []res=new int[n];
        for(i=0;i<n;i++) {
        	arr[i]=scan.nextInt();
        }
        res[0]=(arr[0]+arr[1])/2;
        res[n-1]=(arr[n-2]+arr[n-1])/2;
        for(i=1;i<=n-2;i++) {
        	res[i]=(arr[i-1]+arr[i+1]+arr[i])/3;
        }
        for(i=0;i<n;i++) {
        	System.out.print(res[i]);
        	System.out.print(' ');
        }
	}
	    
}

6.买菜

问题描述

小H和小W来到了一条街上,两人分开买菜,他们买菜的过程可以描述为,去店里买一些菜然后去旁边的一个广场把菜装上车,两人都要买n种菜,所以也都要装n次车。具体的,对于小H来说有n个不相交的时间段[a1,b1],[a2,b2]…[an,bn]在装车,对于小W来说有n个不相交的时间段[c1,d1],[c2,d2]…[cn,dn]在装车。其中,一个时间段[s, t]表示的是从时刻s到时刻t这段时间,时长为t-s。
  由于他们是好朋友,他们都在广场上装车的时候会聊天,他们想知道他们可以聊多长时间。
  
输入格式

输入的第一行包含一个正整数n,表示时间段的数量。
  接下来n行每行两个数ai,bi,描述小H的各个装车的时间段。
  接下来n行每行两个数ci,di,描述小W的各个装车的时间段。
  
输出格式

输出一行,一个正整数,表示两人可以聊多长时间。
  
样例输入

4
1 3
5 6
9 13
14 15
2 4
5 7
10 11
13 14

样例输出

3

数据规模和约定

对于所有的评测用例,1 ≤ n ≤ 2000, ai < bi < ai+1,ci < di < ci+1,对于所有的i(1 ≤ i ≤ n)有,1 ≤ ai, bi, ci, di ≤ 1000000。


import java.util.*;

public class Main{
	
	public static void main(String[] args) {
	
	    Scanner scan = new Scanner(System.in);
        int n=scan.nextInt();
        int i,j;
        int sum=0;
        int u=0;
        int [][]arr1=new int[n][2];
        int [][]arr2=new int[n][2];
        for(i=0;i<n;i++) {
        	arr1[i][0]=scan.nextInt();
        	arr1[i][1]=scan.nextInt();
        }
        for(i=0;i<n;i++) {
        	arr2[i][0]=scan.nextInt();
        	arr2[i][1]=scan.nextInt();
        }
        for(i=0;i<n;i++) {
        	for(j=0;j<n;j++) {
	        	u=Math.min(arr1[i][1], arr2[j][1])-Math.max(arr1[i][0], arr2[j][0]);
	        	if(u>0) 
	        		sum+=u;	        	
        	}    	
        }
        System.out.println(sum);      
	}    
}

7.跳一跳

在这里插入图片描述


import java.util.*;

public class Main{
	
	public static void main(String[] args) {
	
	    Scanner scan = new Scanner(System.in);
        int n,sum;
        sum=0;
        int flag=0;
        while( (n=scan.nextInt())!=0) {
    	  if(n==1) {
    		  flag=0;
    		  sum=sum+1;
    	  }else if(n==2) {
    		  flag++;
    		  sum=sum+2*flag;
    	  }
       }
       System.out.println(sum);
	}    
}

8.碰撞的小球

问题描述

数轴上有一条长度为L(L为偶数)的线段,左端点在原点,右端点在坐标L处。有n个不计体积的小球在线段上,开始时所有的小球都处在偶数坐标上,速度方向向右,速度大小为1单位长度每秒。
  当小球到达线段的端点(左端点或右端点)的时候,会立即向相反的方向移动,速度大小仍然为原来大小。
  当两个小球撞到一起的时候,两个小球会分别向与自己原来移动的方向相反的方向,以原来的速度大小继续移动。
  现在,告诉你线段的长度L,小球数量n,以及n个小球的初始位置,请你计算t秒之后,各个小球的位置。
提示
  因为所有小球的初始位置都为偶数,而且线段的长度为偶数,可以证明,不会有三个小球同时相撞,小球到达线段端点以及小球之间的碰撞时刻均为整数。
  同时也可以证明两个小球发生碰撞的位置一定是整数(但不一定是偶数)。
  
输入格式

输入的第一行包含三个整数n, L, t,用空格分隔,分别表示小球的个数、线段长度和你需要计算t秒之后小球的位置。
  第二行包含n个整数a1, a2, …, an,用空格分隔,表示初始时刻n个小球的位置。
输出格式

输出一行包含n个整数,用空格分隔,第i个整数代表初始时刻位于ai的小球,在t秒之后的位置。
  
样例输入

3 10 5
4 6 8

样例输出

7 9 9
样例说明

在这里插入图片描述
在这里插入图片描述
样例输入

10 22 30
14 12 16 6 10 2 8 20 18 4
样例输出

6 6 8 2 4 0 4 12 10 2

数据规模和约定

对于所有评测用例,1 ≤ n ≤ 100,1 ≤ t ≤ 100,2 ≤ L ≤ 1000,0 < ai < L。L为偶数。
保证所有小球的初始位置互不相同且均为偶数。


import java.util.*;

public class Main{
	
	public static void main(String[] args) {
	
	    Scanner scan = new Scanner(System.in);
       
        int n=scan.nextInt();
        int L=scan.nextInt();
        int t=scan.nextInt();
        int i,j,k,g;
        Ball []arr=new Ball[n];
        //初始化
        for(i=0;i<n;i++) {
        	int x=scan.nextInt();       	
        	arr[i]=new Ball(x);
        }
        for(i=1;i<=t;i++) {
        	for(j=0;j<n;j++) {
        		//碰到边界改变方向
        		if(arr[j].getLoc()==L||arr[j].getLoc()==0) {
    				arr[j].changeDir();
    			}
        		//遍历每一个别的小球若碰撞改变方向
        		for(k=0;k<n;k++) {
        			if(arr[j].getLoc()==arr[k].getLoc()&&j!=k&&arr[j].getDir()!=arr[k].getDir()) {
        				arr[j].changeDir();
        				arr[k].changeDir();
        			}
        			
        		}
        		//移动
        		arr[j].go();
        	}
        	
        }
        for(g=0;g<n;g++) {
         	System.out.print(arr[g].getLoc());
         	System.out.print(" ");
        }
	}
        
}
//定义一个小球类
class Ball{
	int loc,d;//小球的位置和方向
	public Ball(int a){
		this.loc=a;
		this.d=1;
	}
	//获取小球位置
	public int getLoc() {
		return this.loc;
	}
	//获取小球方向
	public int getDir() {
		return this.d;
	}
	//改变方向
	public void changeDir() {
		
		if(this.d==1) {
			this.d=0;
		}else {
			this.d=1;
		}
		
	}
	//移动
	public void go() {
		if(this.d==1) {
			this.loc++;
		}else {
			this.loc--;
		}
	}	
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值