蓝桥杯31天冲刺 Day3

蓝桥杯31天冲刺 Day3

    • 年龄巧合
    • 纸牌三角形
      • 关于全排列
    • 取球游戏

年龄巧合

链接: 年龄巧合.
蓝桥杯31天冲刺 Day3_第1张图片
题目很简单,直接根据题意枚举就好了
但是要注意的是:小明的表弟也满足题意的出生年份,也就是说,我们要求靠前(也就是靠前的年份)
因为这题是填空题,就需要格外小心

代码:

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
      int n=2005;
        while(true){
            n--;
            int a = n/1000;
            int b =n%1000/100;
            int c =n%100/10;
            int d= n%10;
            if(a+b+c+d == 2014-n){
              System.out.println(n);
              break;
            }
        }
    }
}

纸牌三角形

链接: 纸牌三角形.
蓝桥杯31天冲刺 Day3_第2张图片
本质上就是对数组中的数字进行全排列,筛选出满足条件的排列数再除以3(三角形关于三条轴对称)再除以2(排除镜面对称)

关于全排列

全排列本质就是BFS,我们拿 将数字123进行全排列这个基本问题来举例:

首先,想要将123进行全排列我们应该如何缩小问题规模?
我们可以采用一个很基本的想法,固定第一个数字:再对剩下的数字进行全排列我们就得出了整个全排列结果的三分之一结果了。
想要得出所有情况的结果,我们遍历将所有数字,将它们都打头一次就好了。
而要使不同数字打头,我们进行swap操作就好了。

关于传入参数的设计

  • 含有123的nums数组
  • 要进行全排列数组的起始下标start
  • 要进行全排列数组的终止下标end

递归终止条件
最最最最基本的情况,就是start==end,也就是需要排列元素只有1个。此时,也说明前面位置的元素位置全部都已经确定好了(同时当前位置,也就是最后一个元素也已经确定下来了),这个时候,我们直接输出内容就好了

代码:

package test;

import java.util.Arrays;

public class 全排列 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        int[] nums = {1, 2, 3};
        //System.out.println(Arrays.toString(nums));
        allSort(nums,0,2);
	}
	
	private static void allSort(int[] nums, int start, int end) {
		if(start == end) {
			System.out.println(Arrays.toString(nums));
			return;
		}
		
		for(int i =start;i<=end;i++) {
			swap(nums,start,i);
			allSort(nums,start+1,end);
			swap(nums,start,i);
		}
	}
	
	private static void swap(int[] nums,int a, int b) {
		int tmp = nums[a];
		nums[a]=nums[b];
		nums[b]=tmp;
	}

}

好的,再回到我们这题,结合全排列和去重的方法,我们缝合一下,很容易就可以得到最后结果
其中,我们规定数组中存储的数据在三角形中对应的位置:
蓝桥杯31天冲刺 Day3_第3张图片

package 题库;
import java.util.*;

public class 纸牌三角形 {
    static int count=0;
	public static void main(String[] args) {
		//模拟牌面数字
		int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9};

		allSort(nums,0,8);
		System.out.println(count/6);
	}
	
	private static void allSort(int[] nums,int start,int end) {
		if(start == end) {
			//用A B C分别表示三角形的三条边
			int A = nums[0]+nums[1]+nums[2]+nums[3];
			int B = nums[3]+nums[4]+nums[5]+nums[6];
			int C = nums[6]+nums[7]+nums[8]+nums[0];
			if(A==B&&B==C) {
				count++;
			}
			return;
		}
		
		for(int i =start;i<=end;i++) {
			swap(nums,start,i);
			allSort(nums,start+1,end);
			swap(nums,start,i);
		}
	}
	
	private static void swap(int[] nums,int a, int b) {
		int tmp = nums[a];
		nums[a]=nums[b];
		nums[b]=tmp;
	}
}

我们可以看到,只要把全排列的输出功能换成题意需要完成的过程就可以了

取球游戏

链接: 取球游戏.
蓝桥杯31天冲刺 Day3_第4张图片
很基础的博弈思想

我们可以这样思考:但凡是会输的情况,加上1,3,7,8个球,A就一定会赢
根据这种规律,我们直接把范围内的所有情况都算出来就好了

package 题库;
import java.util.*;

public class 取球游戏 {
	private static boolean res[] = new boolean[10020];
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for(int i =1;i<=10000;i++) {
			if(res[i] == false) {
				res[i+1]=true;
				res[i+3]=true;
				res[i+7]=true;
				res[i+8]=true;
			}
		}
        Scanner sc = new Scanner(System.in);
       
        while(sc.hasNext()) {
        	int n = sc.nextInt();
        	for(int i =0;i<n;i++) {
        		int x = sc.nextInt();
        		System.out.println(res[x] ? 1 : 0);
        	}
        }
	}
//	private static void getRes(boolean[] res,int i) {
//		if(i>10000) {
//			return;
//		}
//		res[i] = true;
//		getRes(res,i+1);
//		getRes(res,i+3);
//		getRes(res,i+7);
//		getRes(res,i+8);
//	}

}

底下有我犯蠢写的递归算法耗时实在太长了。所以并非要枚举情况的时候千万别用递归!!!

你可能感兴趣的:(蓝桥杯,算法)