一、日期问题
遇到计算XX年X月X日到YY年Y月Y日的问题,可以通过Calendar类和Date类去解决问题,代码如下
package lianxi;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
//计算日期间有多少天、或者用excel表计算更方便
public class 日期问题 {
public static void main(String[] args) throws ParseException {
String day1="1921-7-23";
String day2="2020-7-1";
SimpleDateFormat format1=new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat format2=new SimpleDateFormat("yyyy-MM-dd");
Date date1=format1.parse(day1);
Date date2=format2.parse(day2);
Calendar calendar1=Calendar.getInstance();
Calendar calendar2=Calendar.getInstance();
calendar1.setTime(date1);
calendar2.setTime(date2);
long time1=calendar1.getTimeInMillis();
long time2=calendar2.getTimeInMillis();
long sum=(time2-time1)/(1000*60*60*24);
System.out.println(sum);
}
}
首先设定开始和结尾日期的字符串
然后申请两个SimpleDateFormat的格式变量,然后定义新的Date 通过调用format.parse(day)的方法,将字符串放入format内,之后通过calendar申请日历,并且用settime设置时间,最后通过time2-time1的方式再除了10006060*24可以获得间隔多少天。
更加便捷的方法是通过excel进行操作,如下:
二、迷宫问题
首先是创建box类,定义x和y坐标
static class box{
int x;
int y;
}
其次定义判定方法ff和check
public static boolean ff(box[] bb,int n,int m)
{ int len=bb.length;
for (int i = 0; i <len; i++) {
if (bb[i].x==n&&bb[i].y==m)
{
return true;
}
}
return false;
}
public static void check(box[] bb)
{ int a[][]={{1,0},{-1,0},{0,1},{0,-1}};//4,2
int len=bb.length;
int n=0,m=0;
int b[][]={{1,1},{-1,-1},{-1,1},{1,-1}};
int[] sum = new int[5];
for (int i = 0; i < len; i++) {
int x=bb[i].x;
int y=bb[i].y;
int flag=0;
for (int j = 0; j < 4; j++) {
n=x+a[j][0];
m=y+a[j][1];
if (ff(bb,n,m))
{
flag++;
}
}
if (flag==4)
{ int temp=0;
for (int j = 0; j < 4; j++) {
n=x+b[j][0];
m=y+b[j][1];
if (ff(bb,n,m))
{
temp++;
}
}
sum[temp]++;
}
}
for (int i = 0; i < sum.length; i++) {
System.out.println(sum[i]);
}
}
剩下的就是主函数main的正常输入输出
值得一提的是除了Scanner方法以外,还可以使用BufferedReader方法,在刷题的时候发现庞大的数据使用Scanner的话所需的时间是非常大。
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String str= bufferedReader.readLine();
int n=Integer.valueOf(str);
box[] bb = new box[n];
for (int i = 0; i < n; i++) {
bb[i]=new box();
str=bufferedReader.readLine();
String s[]=str.trim().split(" ");
bb[i].x=Integer.valueOf(s[0]);
bb[i].y=Integer.valueOf(s[1]);
}
check(bb);
}
唯一要注意的是好像BufferedReader每次只能读取一行,所以需要对读取的字符串进行split的操作
三、稀疏向量CSP
这个解法我借阅了CSDN的大神,第一次输入正常录入数据,第二组则是边检查边录入,可以剩下不少时间,虽然所用的时间也不短,但相比我之前的方法可以达到满分
package lianxi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
//稀疏向量
public class ccf04 {
public static void main(String[] args) throws IOException {
//BufferedReader读取快
BufferedReader scanner = new BufferedReader(new InputStreamReader(System.in));
String str=scanner.readLine();
String s[]=str.trim().split(" ");
int n= Integer.valueOf(s[0]);
int a = Integer.valueOf(s[1]);
int b = Integer.valueOf(s[2]);
HashMap<Integer, Integer> arr = new HashMap<>();
for (int i = 0; i <a; i++) {
str=scanner.readLine();
String sa[]=str.trim().split(" ");
arr.put(Integer.valueOf(sa[0]),Integer.valueOf(sa[1]));
}
long res=0;
int index=0;
int value=0;
for (int i = 0; i < b; i++) {
str=scanner.readLine();
String sb[]=str.trim().split(" ");
index=Integer.valueOf(sb[0]);
value=Integer.valueOf(sb[1]);
if (value!=0&&arr.containsKey(index))
{
res+=value*arr.get(index);
}
}
System.out.println(res);
}
}
四、线性分类器CSP
这道题整体上还是蛮简单的,初次尝试我想用的是边录入边检查放入数组内,希望可以节省运行时间,最后发现对数据的判定很奇怪;参考网上的答案后,建议是用更暴力的方法即可
package lianxi;
import java.util.ArrayList;
import java.util.Scanner;
//线性分类器
class box{
int x;
int y;
String type;
}
public class ccf03 {
public static void check(int x0,int x1,int x2,box b[],int a[],int n){
int len=b.length;
boolean flag=true;
for (int i = 0; i <len-1; i++) {
if (b[i].type.equals(b[i + 1].type)) {
if ((x0 + b[i].x * x1 + b[i].y * x2) * (x0 + b[i + 1].x * x1 + b[i + 1].y * x2) < 0) {
flag=false;
break;
}
} else {
if ((x0 + b[i].x * x1 + b[i].y * x2) * (x0 + b[i + 1].x * x1 + b[i + 1].y * x2) > 0) {
flag=false;
break;
}
}
}
if (flag) {
a[n]=1;
}
else {
a[n]=0;
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n=in.nextInt();//点个数
int m=in.nextInt();//查询个数
box[] boxes = new box[n];
int[] a = new int[m];
for (int i = 0; i < n; i++) {
boxes[i]=new box();
boxes[i].x=in.nextInt();
boxes[i].y=in.nextInt();
boxes[i].type=in.next();
}
for (int i = 0; i < m; i++) {
int x0=in.nextInt();
int x1=in.nextInt();
int x2=in.nextInt();
check(x0,x1,x2,boxes,a,i);
}
for (int i = 0; i < m; i++) {
if (a[i]==1)
System.out.println("Yes");
else
System.out.println("No");
}
}
}
五、数字三角形蓝桥杯
本题解题思路是利用递归,求取最大值,难度不大,编写代码偷懒了一些,只用了一组数据,没用输入的情况
package lianxi;
import java.util.Arrays;
import java.util.Scanner;
//数字三角形
public class lqb05 {
static int n=5;
static int max=0;
static int map1[][]={{7},{3,8},{8,1,0},{2,7,4,4},{4,5,2,6,5}};
public static void main(String[] args) {
dfs(0,0,0);
System.out.println(max);
}
public static void dfs(int i,int j,int sum){
if (i==n-1)
{
sum+=map1[i][j];
if (sum>max)
max=sum;
return;
}
dfs(i+1,j,sum+map1[i][j]);
dfs(i+1,j+1,sum+map1[i][j]);
return;
}
}
之前还遇到过这个题的升级版,是左拐和右拐的次数不能超过1,即需要对路线进行判定,基本上就是在dfs的方法添加两个变量,然后退出的语句再加个判定即可
六 、01背包蓝桥杯
01背包也是老经典的问题了,也是通过递归的解决,比上一题要多考虑的是return的情景,负载重要小于0和可选物品达到要求,以及选择拿和不拿的情况
package lianxi;
//01背包
public class lqb04 {
static int w[]={2,1,3,2};
static int v[]={3,2,4,2};
static int W=5;
static int n=4;
public static void main(String[] args) {
int ww=W;
int ans=dfs(0,ww);
System.out.println(ans);
}
public static int dfs(int i,int ww)
{
if (ww<=0) return 0;
if (i==n) return 0;
int v2=dfs(i+1,ww); //不选择当前物品
if (ww>=w[i])
{
int v1=v[i]+dfs(i+1,ww-w[i]);
return Math.max(v1,v2);
}else
return v2;
}
}
七、素数环蓝桥杯
这题我应该也是参考CSDN的大神的答案,解决方案也是递归,但是对判断又提高了要求
isp函数是对素数的判断
check函数是对已经形成的环进行判定,如数组内已有该元素或判断结果不为素数,则返回false,这里递归使用了回溯的方法,对数进行了全排列,我觉得这道题思路是很明确的,但是实现的函数有一些复杂0 0
package lianxi;
import java.util.Scanner;
//素数环
public class lqb02 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n=in.nextInt(); //输入个数
int a[]=new int[n];
a[0]=1; //初始化a0为1
dfs(a,n,1);
}
public static void dfs(int a[],int n,int cur)
{
if (cur==n&&isp(a[0]+a[n-1]))
{
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
System.out.println();
return;
}
for (int i = 2; i <=n; i++) {
if (check(a,i,cur))
{
a[cur]=i;
dfs(a,n,cur+1);
a[cur]=0;
}
}
}
public static boolean check(int a[],int i,int cur)
{
for (int e:a)
{
if (e==i||!isp(a[cur-1]+i))
return false;
}
return true;
}
public static boolean isp(int k)
{
for (int i = 2; i<k; i++) {
if (k%i==0)
return false;
}
return true;
}
}
八、翻硬币蓝桥杯
翻硬币这道题,是对初始状态和末状态的硬币进行判定,若不同则进行翻硬币操作,每次都翻动相邻的两枚硬币,感觉就是指针的移动,最后判断一下即可,思路很清晰>.<
package lianxi;
import java.util.Scanner;
//翻硬币
public class lqb03 {
static int res=0;
public static void ff(char c1[],char c2[])
{
for (int i = 0; i <c1.length; i++) {
if (c1[i]!=c2[i])
{
if (c1[i]=='*') {
c1[i] = 'o';
if (c1[i+1]=='*')
c1[i+1]='o';
else
c1[i+1]='*';
}
else {
c1[i] = '*';
if (c1[i+1]=='*')
c1[i+1]='o';
else
c1[i+1]='*';
}
res++;
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String str1=in.nextLine();//first
String str2=in.nextLine();//end
char c1[]=str1.toCharArray();
char c2[]=str2.toCharArray();
ff(c1,c2);
System.out.println(res);
}
}
九、放学CSP
这道题我起初想用递归去解决,发现判定的难度非常大,参阅大神的答案发现用累加的方式可能更好,思路更清晰一些,判定的难度也不大,基本上就是加减法,可惜没想出来这个方法
初步的判断是k==0时,tiem直接加t即可
第二步是对time<t的情况进行判定(k=1,2,3已分)
红灯就加剩余的时间t,绿灯直接return,黄灯则需要用t加上红灯的最大时间r;
第三步则是细分time>t的情况
定义temp时间,当k=1初始是红灯情况下,temp=红灯最大时间r+已有时间sum-剩余时间t再对total时间取余,如果temp小于红灯最大时间r,说明经过已有时间sum,还处于红灯的情况,那么就用红灯时间r-temp就是等待时间了,如果是黄灯情况,则用total时间-temp时间,则是等待黄灯的时间,再加上红灯时间,就是该情况所需要的等待时间,绿灯则通过,当k=2/3的情况下,除了对temp的初始化有差别,其余都一致,当k=2黄灯时,则用total+已有时间sum-剩余时间t再对total时间取余,当k=3绿灯时,则用红灯时间r+绿灯时间+已有时间sum-剩余时间t再对total时间取余
package lianxi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ccf放学 {
static int r;
static int y;
static int g;
static int time;
static int total;
public static void ff(int k,int t)
{
if (k==0)
time+=t;
else
{
if (k==1)
{
if (time<t)
{
time=t;
}
else
{
int temp = (r + time - t) % total;
if (temp < r) //红灯
{
temp = r - temp;
time += temp;
}
else if (temp <= r + g)//绿灯
{
return ;
}
else //黄灯
{
temp = total - temp;
temp += r;
time += temp;
}
}
}
else if (k==2)
{
if (time<t)
{
time=t+r;
}
else
{
int temp=(total+time-t)%total;
if (temp<r)//red
{
temp=r-temp;
time+=temp;
}
else if (temp<=r+g)
{
return;
}
else {
//yellow
temp=total-temp;
temp+=r;
time+=temp;
}
}
}
else
{
if (time<t)
{
return;
}
else
{
int temp=(r+g+time-t)%total;
if (temp<r)//red
{
temp=r-temp;
time+=temp;
}
else if (temp<=r+g)
{
return;
}
else {
//yellow
temp=total-temp;
temp+=r;
time+=temp;
}
}
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String s1[]= bufferedReader.readLine().trim().split(" ");
r=Integer.valueOf(s1[0]);
y=Integer.valueOf(s1[1]);
g=Integer.valueOf(s1[2]);
total=r+y+g;
String s2=bufferedReader.readLine();
int n=Integer.valueOf(s2);
for (int i = 0; i < n; i++) {
String s3[]= bufferedReader.readLine().trim().split(" ");
ff(Integer.valueOf(s3[0]),Integer.valueOf(s3[1]));
}
System.out.println(time);
}
}
十、完全二叉树的权值蓝桥杯
题目梗概如下
这道题我还是用偷懒的方法,并没有按照常规的树去建立和计算,直接使用数据和层次的关系解决
因为本题输入是按层次遍历的顺序输入,然后建立方法,其变量有tree数组,层次k,和存放sum和的集合
package lianxi;
import java.util.ArrayList;
import java.util.Scanner;
public class 二叉树权值 {
static int n;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n=scanner.nextInt();
int[] tree = new int[n+1];
ArrayList<Integer> list = new ArrayList<>();
for (int i = 1; i <n+1; i++) {
tree[i]=scanner.nextInt();
}
ff(tree,0,list);
int max=list.get(0);
int temp=0;
for (int i = 1; i < list.size(); i++) {
if (list.get(i)>max)
{
max=list.get(i);
temp=i;
}
}
System.out.println(temp+1);
}
public static void ff(int tree[],int k,ArrayList<Integer> list)
{
int start=(int)Math.pow(2,k);
if (start>n)
{
return;
}
int end=(int)Math.pow(2,k+1);
if (end>n){
end=n;
}
int sum=0;
for (int i =start; i <end ; i++) {
sum+=tree[i];
}
list.add(sum);
ff(tree,k+1,list);
}
}