CCF历年试题解析

CCF题目:小中大
保留一位小数

String result = String.format("%.1f", data);
double result = new BigDecimal(data).setScale(1,BigDecimal.ROUND_HALF_UP).doubleValue();

CCF题目:二十四点
在这里插入图片描述在这里插入图片描述
满分代码:

import java.util.Scanner;
import java.util.Stack;

public class Main {
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		Stack<Integer> num=new Stack<>();
		Stack<Character> op=new Stack<>();
		for(int i=0;i<n;i++)
		{
			num.clear();
			op.clear();
			String s=scan.next();
			char[] c=s.toCharArray();
			num.push(c[0]-'0');
			int k_num=0;
			int k_op=-1;
			while(k_num<6)
			{
				k_num+=2;
				k_op+=2;
				//加减运算注意先后顺序,这里采用将减法变为加法
				if(c[k_op]=='-')
				{
					num.push((-1)*(c[k_num]-'0'));
					op.push('+');
				}
				else
				{
					num.push(c[k_num]-'0');
					op.push(c[k_op]);
				}
				if(op.peek().equals('x'))
				{
					op.pop();
					int a=num.pop();
					int b=num.pop();
					num.push(a*b);
				}
				else if(op.peek().equals('/'))
				{
					op.pop();
					int a=num.pop();
					int b=num.pop();
					num.push(b/a);
				}
			}
			while(!op.empty())
			{
				if(op.peek().equals('+'))
				{
					op.pop();
					int a=num.pop();
					int b=num.pop();
					num.push(a+b);
				}
			}
			if(num.get(0)==24)
				System.out.println("Yes");
			else
				System.out.println("No");
		}
		scan.close();
	}
}
//第一遍只有30分   Hack数据:3x8-3+3,没有注意加减的先后顺序

测试结果:
在这里插入图片描述
附上一位大佬更清晰的解题思路:
https://blog.csdn.net/wingrez/article/details/88676235

CCF题目:俄罗斯方块
问题描述
试题编号: 201604-2
试题名称: 俄罗斯方块
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  俄罗斯方块是俄罗斯人阿列克谢·帕基特诺夫发明的一款休闲游戏。
  游戏在一个15行10列的方格图上进行,方格图上的每一个格子可能已经放置了方块,或者没有放置方块。每一轮,都会有一个新的由4个小方块组成的板块从方格图的上方落下,玩家可以操作板块左右移动放到合适的位置,当板块中某一个方块的下边缘与方格图上的方块上边缘重合或者达到下边界时,板块不再移动,如果此时方格图的某一行全放满了方块,则该行被消除并得分。
  在这个问题中,你需要写一个程序来模拟板块下落,你不需要处理玩家的操作,也不需要处理消行和得分。
  具体的,给定一个初始的方格图,以及一个板块的形状和它下落的初始位置,你要给出最终的方格图。
输入格式
  输入的前15行包含初始的方格图,每行包含10个数字,相邻的数字用空格分隔。如果一个数字是0,表示对应的方格中没有方块,如果数字是1,则表示初始的时候有方块。输入保证前4行中的数字都是0。
  输入的第16至第19行包含新加入的板块的形状,每行包含4个数字,组成了板块图案,同样0表示没方块,1表示有方块。输入保证板块的图案中正好包含4个方块,且4个方块是连在一起的(准确的说,4个方块是四连通的,即给定的板块是俄罗斯方块的标准板块)。
  第20行包含一个1到7之间的整数,表示板块图案最左边开始的时候是在方格图的哪一列中。注意,这里的板块图案指的是16至19行所输入的板块图案,如果板块图案的最左边一列全是0,则它的左边和实际所表示的板块的左边是不一致的(见样例)
输出格式
  输出15行,每行10个数字,相邻的数字之间用一个空格分隔,表示板块下落后的方格图。注意,你不需要处理最终的消行。
样例输入
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 0 0 0 1 1 1 1
0 0 0 0 1 0 0 0 0 0
0 0 0 0
0 1 1 1
0 0 0 1
0 0 0 0
3
样例输出
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 1 0 0 0 0

满分代码:

import java.util.Scanner;
import java.util.Stack;

public class Main {
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		int m=15;
		int n=10;
		int[][] map=new int[m][n];
		//输入15*10方格图
		for(int i=0;i<m;i++)
			for(int j=0;j<n;j++)
			{
				map[i][j]=scan.nextInt();
			}
		int moveM=4;
		int moveN=4;
		int[][] move=new int[moveM][moveN];
		int[] xIndex=new int[moveM];
		int[] yIndex=new int[moveN];
		int count=0;
		//输入下落板块,并记录4个小方块的位置坐标
		for(int i=0;i<moveM;i++)
			for(int j=0;j<moveN;j++)
			{
				move[i][j]=scan.nextInt();
				if(move[i][j]==1)
				{
					xIndex[count]=i;
					yIndex[count]=j;
					count++;
				}
			}
		//输入板块图案最左边开始列位置
		int col_start=scan.nextInt();
		col_start--;
		scan.close();
		//将板块对齐到方格图
		for(int i=0;i<moveM;i++)
		{
			yIndex[i]+=col_start;
		}
		boolean isFlag=false;
		A:for(int j=0;j<m;j++)
		{
			for(int i=col_start;i<col_start+moveM;i++)
			{
				//到达边缘或板块下落过程中下一行有方块
				if(xIndex[moveM+col_start-i-1]+1==15||map[xIndex[moveM+col_start-i-1]+1][yIndex[moveM+col_start-i-1]]==1)
				{
					isFlag=true;
					break A;
				}
				else
					;
			}
			//没有发生碰撞,板块下落一行
			if(isFlag==false)
			{
				for(int k=0;k<moveM;k++)
					xIndex[k]++;
			}
		}
		if(isFlag==true)
		{
			//找到板块下落位置,修改方格图
			for(int i=0;i<moveM;i++)
			{
				map[xIndex[i]][yIndex[i]]=1;
			}
			//结果输出
			for(int i=0;i<m;i++)
			{
				for(int j=0;j<n-1;j++)
				{
					System.out.print(map[i][j]+" ");
				}
				System.out.print(map[i][n-1]);
				System.out.println();
			}
		}
	}
}

在这里插入图片描述
CCF题目:火车购票
试题编号: 201609-2
试题名称: 火车购票
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配。
  假设一节车厢有20排、每一排5个座位。为方便起见,我们用1到100来给所有的座位编号,第一排是1到5号,第二排是6到10号,依次类推,第20排是96到100号。
  购票时,一个人可能购一张或多张票,最多不超过5张。如果这几张票可以安排在同一排编号相邻的座位,则应该安排在编号最小的相邻座位。否则应该安排在编号最小的几个空座位中(不考虑是否相邻)。
  假设初始时车票全部未被购买,现在给了一些购票指令,请你处理这些指令。
输入格式
  输入的第一行包含一个整数n,表示购票指令的数量。
  第二行包含n个整数,每个整数p在1到5之间,表示要购入的票数,相邻的两个数之间使用一个空格分隔。
输出格式
  输出n行,每行对应一条指令的处理结果。
  对于购票指令p,输出p张车票的编号,按从小到大排序。
样例输入
4
2 5 4 2
样例输出
1 2
6 7 8 9 10
11 12 13 14
3 4
样例说明
  1) 购2张票,得到座位1、2。
  2) 购5张票,得到座位6至10。
  3) 购4张票,得到座位11至14。
  4) 购2张票,得到座位3、4。
评测用例规模与约定
  对于所有评测用例,1 ≤ n ≤ 100,所有购票数量之和不超过100。

import java.util.*;

public class Main {
	static int n;
	static int[] lin_max;
	static int[][] pos_flag;
	static ArrayList<Integer> list;
	public static void search(int xuhao,int num)
	{
		list=new ArrayList<>();
		int hang_num=1;
		while(lin_max[hang_num]<num) 
		{
			hang_num++;
		}
		int count=0;
		for(int j=1;j<=5;j++)
		{
			if(pos_flag[hang_num][j]==0)
			{
				pos_flag[hang_num][j]=1;
				list.add((hang_num-1)*5+j);
				count++;
				if(count==num) 
				{
					lin_max[hang_num]-=num;
					break;
				}
			}
		}
		for(int i=0;i<num;i++)
		{
			System.out.print(list.get(i)+" ");
		}
		System.out.println();
	}
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		n=scan.nextInt();
		int[] piao_num=new int[n];
		for(int i=0;i<n;i++)
		{
			piao_num[i]=scan.nextInt();
		}
		scan.close();
		lin_max=new int[21];//1-20
		for(int i=1;i<=20;i++)
			lin_max[i]=5;
		//每排最小编号  (n-1)*5+1
		int[] min_num=new int[21];
		for(int i=1;i<=20;i++)
			min_num[i]=(i-1)*5+1;
		pos_flag=new int[21][6];//20*5
		for(int i=0;i<n;i++)
		{
			search(i,piao_num[i]);
		}
	}
}

在这里插入图片描述
CCF题目:公共钥匙盒
试题编号: 201709-2
试题名称: 公共钥匙盒
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  有一个学校的老师共用N个教室,按照规定,所有的钥匙都必须放在公共钥匙盒里,老师不能带钥匙回家。每次老师上课前,都从公共钥匙盒里找到自己上课的教室的钥匙去开门,上完课后,再将钥匙放回到钥匙盒中。
  钥匙盒一共有N个挂钩,从左到右排成一排,用来挂N个教室的钥匙。一串钥匙没有固定的悬挂位置,但钥匙上有标识,所以老师们不会弄混钥匙。
  每次取钥匙的时候,老师们都会找到自己所需要的钥匙将其取走,而不会移动其他钥匙。每次还钥匙的时候,还钥匙的老师会找到最左边的空的挂钩,将钥匙挂在这个挂钩上。如果有多位老师还钥匙,则他们按钥匙编号从小到大的顺序还。如果同一时刻既有老师还钥匙又有老师取钥匙,则老师们会先将钥匙全还回去再取出。
  今天开始的时候钥匙是按编号从小到大的顺序放在钥匙盒里的。有K位老师要上课,给出每位老师所需要的钥匙、开始上课的时间和上课的时长,假设下课时间就是还钥匙时间,请问最终钥匙盒里面钥匙的顺序是怎样的?
输入格式
  输入的第一行包含两个整数N, K。
  接下来K行,每行三个整数w, s, c,分别表示一位老师要使用的钥匙编号、开始上课的时间和上课的时长。可能有多位老师使用同一把钥匙,但是老师使用钥匙的时间不会重叠。
  保证输入数据满足输入格式,你不用检查数据合法性。
输出格式
  输出一行,包含N个整数,相邻整数间用一个空格分隔,依次表示每个挂钩上挂的钥匙编号。
样例输入
5 2
4 3 3
2 2 7
样例输出
1 4 3 2 5
样例说明
  第一位老师从时刻3开始使用4号教室的钥匙,使用3单位时间,所以在时刻6还钥匙。第二位老师从时刻2开始使用钥匙,使用7单位时间,所以在时刻9还钥匙。
  每个关键时刻后的钥匙状态如下(X表示空):
  时刻2后为1X345;
  时刻3后为1X3X5;
  时刻6后为143X5;
  时刻9后为14325。
样例输入
5 7
1 1 14
3 3 12
1 15 12
2 7 20
3 18 12
4 21 19
5 30 9
样例输出
1 2 3 5 4
评测用例规模与约定
  对于30%的评测用例,1 ≤ N, K ≤ 10, 1 ≤ w ≤ N, 1 ≤ s, c ≤ 30;
  对于60%的评测用例,1 ≤ N, K ≤ 50,1 ≤ w ≤ N,1 ≤ s ≤ 300,1 ≤ c ≤ 50;
  对于所有评测用例,1 ≤ N, K ≤ 1000,1 ≤ w ≤ N,1 ≤ s ≤ 10000,1 ≤ c ≤ 100。
满分代码:

import java.util.*;

public class Main {
	//数字元素类型定义  钥匙号、借(还)时间
	static class Node implements Comparable<Node>
	{
		int num;
		int br_time;
		Node(int a,int b)
		{
			num=a;
			br_time=b;
		}
		@Override
		//先按借(还)时间排序,后按钥匙号排序
		public int compareTo(Node o) {
			// TODO Auto-generated method stub
			if(br_time==o.br_time) return num-o.num;
			else return br_time-o.br_time;
		}
	}
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int k=scan.nextInt();
		//借钥匙和还钥匙分为两个事件
		Node[] borrow=new Node[k];
		Node[] returnn=new Node[k];
		for(int i=0;i<k;i++)
		{
			int num=scan.nextInt();
			int borrow_time=scan.nextInt();
			int return_time=scan.nextInt();
			borrow[i]=new Node(num,borrow_time);
			returnn[i]=new Node(num,borrow_time+return_time);
		}
		Arrays.sort(borrow);
		Arrays.sort(returnn);
		int[] flag=new int[n+1];//1-n号钥匙 初始状态为1   判断钥匙存在与否
		for(int i=1;i<n+1;i++)
		{
			flag[i]=1;
		}
		int[] pos=new int[n+1];//存放钥匙的位置  初始状态1,2,3,4,5
		for(int i=1;i<n+1;i++)
		{
			pos[i]=i;
		}
		scan.close();
//		for(int i=0;i<k;i++)
//		{
//			System.out.println(borrow[i].num+" "+borrow[i].br_time);
//		}
//		for(int i=0;i<k;i++)
//		{
//			System.out.println(returnn[i].num+" "+returnn[i].br_time);
//		}
		//寻找最早借钥匙时间和最晚还钥匙时间
		int min_borrow_time=10000;
		int max_return_time=0;
		for(int i=0;i<k;i++)
		{
			if(min_borrow_time>borrow[i].br_time)
				min_borrow_time=borrow[i].br_time;
			if(max_return_time<returnn[i].br_time)
				max_return_time=returnn[i].br_time;
		}
		//模拟借还过程
		for(int i=min_borrow_time;i<=max_return_time;i++)
		{
			//先还钥匙
			for(int j=0;j<k;j++)
			{
				if(returnn[j].br_time==i&&flag[returnn[j].num]==0)
				{
					flag[returnn[j].num]=1;
					//从左向右寻找空位放钥匙
					for(int m=1;m<=n;m++)
					{
						if(pos[m]==-1)
						{
							pos[m]=returnn[j].num;
							break;
						}
					}
				}
			}
			//再借钥匙
			for(int j=0;j<k;j++)
			{
				if(borrow[j].br_time==i&&flag[borrow[j].num]==1)
				{
					flag[borrow[j].num]=0;
					//从左向右寻找要借的钥匙
					for(int m=1;m<=n;m++)
					{
						if(pos[m]==borrow[j].num)
						{
							pos[m]=-1;
							break;
						}
					}
				}
			}
		}
		//结果打印
		for(int i=1;i<=n;i++)
		{
			System.out.print(pos[i]+" ");
		}	
	}
}

测试结果:
在这里插入图片描述
试题编号: 201712-2
试题名称: 游戏
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  有n个小朋友围成一圈玩游戏,小朋友从1至n编号,2号小朋友坐在1号小朋友的顺时针方向,3号小朋友坐在2号小朋友的顺时针方向,……,1号小朋友坐在n号小朋友的顺时针方向。
  游戏开始,从1号小朋友开始顺时针报数,接下来每个小朋友的报数是上一个小朋友报的数加1。若一个小朋友报的数为k的倍数或其末位数(即数的个位)为k,则该小朋友被淘汰出局,不再参加以后的报数。当游戏中只剩下一个小朋友时,该小朋友获胜。
  例如,当n=5, k=2时:
  1号小朋友报数1;
  2号小朋友报数2淘汰;
  3号小朋友报数3;
  4号小朋友报数4淘汰;
  5号小朋友报数5;
  1号小朋友报数6淘汰;
  3号小朋友报数7;
  5号小朋友报数8淘汰;
  3号小朋友获胜。

给定n和k,请问最后获胜的小朋友编号为多少?
输入格式
  输入一行,包括两个整数n和k,意义如题目所述。
输出格式
  输出一行,包含一个整数,表示获胜的小朋友编号。
样例输入
5 2
样例输出
3
样例输入
7 3
样例输出
4
数据规模和约定
  对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ k ≤ 9。

import java.util.*;

public class Main {
	static class Node
	{
		public int data;
		Node nextNode;
		public Node(int a)
		{
			this.data=a;
			this.nextNode=null;
		}
		public Node()
		{
			this.nextNode=null;
		}
		public void setNextNode(Node nextNode)
		{
			this.nextNode=nextNode;
		}
	}
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int k=scan.nextInt();
		scan.close();
		Node q=new Node(-1);
		Node p=q;
		for(int i=1;i<=n;i++)
		{
			Node node=new Node(i);
			q.setNextNode(node);
			q=node;
		}
		q.setNextNode(p.nextNode);
		q=p.nextNode;
		int i=1;
		while(p!=q)
		{
			if(i%k==0||i%10==k)
			{
				q=q.nextNode;
				p.nextNode=q;
			}
			else
			{
				p=p.nextNode;
				q=q.nextNode;
			}
			i++;
		}
		System.out.print(p.data);	
	}
}

在这里插入图片描述
满分代码:

import java.util.*;

public class Main {
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int k=scan.nextInt();
		scan.close();
		Queue<Integer> queue=new LinkedList<>();
		for(int i=1;i<=n;i++)
		{
			queue.add(i);
		}
		int num=1;
		while(queue.size()!=1)
		{
			int m=queue.poll();
			if(num%k!=0&&num%10!=k)
			{
				queue.add(m);
			}
			num++;
		}
		System.out.print(queue.poll());
	}
}

在这里插入图片描述
试题编号: 201809-2
试题名称: 买菜
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  小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。
满分代码:

//用数组t[]代表时间轴,先初始化为0,小H装车对应时间段+1,小W装车对应时间段也+1,则统计完成后t[]为2的时间说明两人都在装车,用time记录t[]=2的数量即为所求
import java.util.*;

public class Main {
	static int N=1000001;
	static int[] t=new int[N];
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		for(int i=0;i<n;i++)
		{
			int a=scan.nextInt();
			int b=scan.nextInt();
			for(int j=a;j<b;j++)
			{
				t[j]+=1;
			}
		}
		for(int i=0;i<n;i++)
		{
			int a=scan.nextInt();
			int b=scan.nextInt();
			for(int j=a;j<b;j++)
			{
				t[j]+=1;
			}
		}
		scan.close();
		int count=0;
		for(int i=1;i<=1000000;i++)
		{
			if(t[i]==2) count++;
		}
		System.out.print(count);
	}
}

测试结果:
在这里插入图片描述
试题编号: 201812-2
试题名称: 小明放学
时间限制: 1.0s
内存限制: 512.0MB
问题描述:
题目背景
  汉东省政法大学附属中学所在的光明区最近实施了名为“智慧光明”的智慧城市项目。具体到交通领域,通过“智慧光明”终端,可以看到光明区所有红绿灯此时此刻的状态。小明的学校也安装了“智慧光明”终端,小明想利用这个终端给出的信息,估算自己放学回到家的时间。
问题描述
  一次放学的时候,小明已经规划好了自己回家的路线,并且能够预测经过各个路段的时间。同时,小明通过学校里安装的“智慧光明”终端,看到了出发时刻路上经过的所有红绿灯的指示状态。请帮忙计算小明此次回家所需要的时间。
输入格式
  输入的第一行包含空格分隔的三个正整数 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。

import java.io.*;
import java.util.*;

public class Main {
	public static void main(String[] args) throws IOException
	{
		BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
		long[] light=new long[3];//0红  1绿  2黄
		String s=reader.readLine();
		String[] ss=s.split(" ");
		light[0]=Long.valueOf(ss[0]);//红
		light[2]=Long.valueOf(ss[1]);//黄
		light[1]=Long.valueOf(ss[2]);//绿
		long sum=light[0]+light[1]+light[2];//红绿灯变换一周的总时长
		int n=Integer.parseInt(reader.readLine());
		long ans=0;
		for(int i=0;i<n;i++)
		{
			String s1=reader.readLine();
			String[] ss1=s1.split(" ");
			int k=Integer.parseInt(ss1[0]);
			long t=Long.valueOf(ss1[1]);
			if(k==0)
			{
				ans+=t;
			}
			else//是红绿灯
			{
				if(k==1) k=0;
				else if(k==3) k=1;
				t=(light[k]-t+ans)%sum;//红绿灯变换的最后一周的时长
				while(t>light[k])//若t比当前红绿灯时长 长
				{
					t-=light[k];//减去当前的红绿灯时长
					k=(k+1)%3;//转向下一个灯
				}
				if(k==0)//红灯
					ans+=light[k]-t;//加上红灯剩余时长
				else if(k==2)//黄灯
					ans+=light[k]-t+light[0];//加上黄灯剩余时长和一个红灯时长
			}
		}
		System.out.print(ans);
	}
}

在这里插入图片描述
试题编号: 201312-2
试题名称: ISBN号码
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符“-”之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔之后的五位数字代表该书在出版社的编号;最后一位为识别码。
  识别码的计算方法如下:
  首位数字乘以1加上次位数字乘以2……以此类推,用所得的结果mod 11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。例如ISBN号码0-670-82162-4中的识别码4是这样得到的:对067082162这9个数字,从左至右,分别乘以1,2,…,9,再求和,即0×1+6×2+……+2×9=158,然后取158 mod 11的结果4作为识别码。
  编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出“Right”;如果错误,则输出是正确的ISBN号码。
输入格式
  输入只有一行,是一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。
输出格式
  输出一行,假如输入的ISBN号码的识别码正确,那么输出“Right”,否则,按照规定的格式,输出正确的ISBN号码(包括分隔符“-”)。
样例输入
0-670-82162-4
样例输出
Right
样例输入
0-670-82162-0
样例输出
0-670-82162-4

import java.io.*;
import java.util.*;

public class Main {
	public static void main(String[] args) throws IOException
	{
		BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
		String s=reader.readLine();
		StringBuilder builder=new StringBuilder(s);
		String[] ss=s.split("-");
		String s1=ss[0]+ss[1]+ss[2];
		char[] a=s1.toCharArray();
		long sum=0;
		for(int i=0;i<a.length;i++)
		{
			sum+=(int)(a[i]-'0')*(i+1);
		}
		sum%=11;
		char c='0';
		if(sum==10) c='X';
		else c=(char)(c+sum);
		
		if(c==ss[3].charAt(0))
		{
			System.out.println("Right");
		}
		else
		{
			System.out.println(builder.substring(0, 12)+c);
		}
	}
}

试题编号: 201403-2
试题名称: 窗口
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  在某图形操作系统中,有 N 个窗口,每个窗口都是一个两边与坐标轴分别平行的矩形区域。窗口的边界上的点也属于该窗口。窗口之间有层次的区别,在多于一个窗口重叠的区域里,只会显示位于顶层的窗口里的内容。
  当你点击屏幕上一个点的时候,你就选择了处于被点击位置的最顶层窗口,并且这个窗口就会被移到所有窗口的最顶层,而剩余的窗口的层次顺序不变。如果你点击的位置不属于任何窗口,则系统会忽略你这次点击。
  现在我们希望你写一个程序模拟点击窗口的过程。
输入格式
  输入的第一行有两个正整数,即 N 和 M。(1 ≤ N ≤ 10,1 ≤ M ≤ 10)
  接下来 N 行按照从最下层到最顶层的顺序给出 N 个窗口的位置。 每行包含四个非负整数 x1, y1, x2, y2,表示该窗口的一对顶点坐标分别为 (x1, y1) 和 (x2, y2)。保证 x1 < x2,y1 2。
  接下来 M 行每行包含两个非负整数 x, y,表示一次鼠标点击的坐标。
  题目中涉及到的所有点和矩形的顶点的 x, y 坐标分别不超过 2559 和  1439。
输出格式
  输出包括 M 行,每一行表示一次鼠标点击的结果。如果该次鼠标点击选择了一个窗口,则输出这个窗口的编号(窗口按照输入中的顺序从 1 编号到 N);如果没有,则输出"IGNORED"(不含双引号)。
样例输入
3 4
0 0 4 4
1 1 5 5
2 2 6 6
1 1
0 0
4 4
0 5
样例输出
2
1
1
IGNORED
样例说明
  第一次点击的位置同时属于第 1 和第 2 个窗口,但是由于第 2 个窗口在上面,它被选择并且被置于顶层。
  第二次点击的位置只属于第 1 个窗口,因此该次点击选择了此窗口并将其置于顶层。现在的三个窗口的层次关系与初始状态恰好相反了。
  第三次点击的位置同时属于三个窗口的范围,但是由于现在第 1 个窗口处于顶层,它被选择。
  最后点击的 (0, 5) 不属于任何窗口。

import java.io.*;
import java.util.*;

public class Main {
	static class window
	{
		int num;
		int x1,x2,y1,y2;
	}
	public static void main(String[] args) throws IOException
	{
		Scanner scan=new Scanner(System.in);
		int N=scan.nextInt();
		int M=scan.nextInt();
		List<window> list=new ArrayList<>();
		for(int i=1;i<=N;i++)
		{
			window w=new window();
			w.num=i;
			w.x1=scan.nextInt();
			w.y1=scan.nextInt();
			w.x2=scan.nextInt();
			w.y2=scan.nextInt();
			list.add(w);
		}
		int[][] b=new int[M][2];
		for(int i=0;i<M;i++)
			for(int j=0;j<2;j++)
		{
			b[i][j]=scan.nextInt();
		}
		scan.close();
		for(int i=0;i<M;i++)
		{
			int x=b[i][0];
			int y=b[i][1];
			int flag=0;
			for(int j=N-1;j>=0;j--)
			{
				if(x>=list.get(j).x1&&x<=list.get(j).x2&&y>=list.get(j).y1&&y<=list.get(j).y2)
				{
					System.out.println(list.get(j).num);
					flag=1;
					window m=list.remove(j);
					list.add(m);
					break;
				}
			}
			if(flag==0) System.out.println("IGNORED");
		}
	}
}

试题编号: 201409-2
试题名称: 画图
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色。
  下图给出了一个画了两个矩形的例子。第一个矩形是(1,1) 到(4, 4),用绿色和紫色表示。第二个矩形是(2, 3)到(6, 5),用蓝色和紫色表示。图中,一共有15个单位的面积被涂上颜色,其中紫色部分被涂了两次,但在计算面积时只计算一次。在实际的涂色过程中,所有的矩形都涂成统一的颜色,图中显示不同颜色仅为说明方便。
在这里插入图片描述
  给出所有要画的矩形,请问总共有多少个单位的面积被涂上颜色。
输入格式
  输入的第一行包含一个整数n,表示要画的矩形的个数。
  接下来n行,每行4个非负整数,分别表示要画的矩形的左下角的横坐标与纵坐标,以及右上角的横坐标与纵坐标。
输出格式
  输出一个整数,表示有多少个单位的面积被涂上颜色。
样例输入
2
1 1 4 4
2 3 6 5
样例输出
15
评测用例规模与约定
  1<=n<=100,0<=横坐标、纵坐标<=100。

import java.io.*;
import java.util.*;

public class Main {
	public static void main(String[] args) throws IOException
	{
		Scanner scan=new Scanner(System.in);
		int N=scan.nextInt();
		int[][] flag=new int[101][101];
		int count=0;
		for(int k=0;k<N;k++)
		{
			int x1=scan.nextInt();
			int y1=scan.nextInt();
			int x2=scan.nextInt();
			int y2=scan.nextInt();
			for(int i=0;i<100;i++)
				for(int j=0;j<100;j++)
				{
					if(flag[i][j]==0&&(i>=x1&&i<x2&&j>=y1&&j<y2))
					{
						flag[i][j]=1;
						count++;
					}
				}
		}
		scan.close();
		System.out.print(count);
	}
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值