第三届全国高校计算机能力挑战赛Java程序设计赛总结

题目1:计算几何题

        二维空间中给定一组点的坐标, 以任息两个点为直径绘制一个圆,求可以绘制的最大圆,满足该圆不包含其他点,输出其直径。说明,圆心0,半径r的圆包含某点P的条件是,r≥(O到P的距离)。

        输入说明:第一行,点的数量,不超过200;第二行开始为点二维坐标,每个点为一行,每个点的两个维度间以空格隔开,坐标值范围为[-10000.0, 10000.0]。

        输出说明:输出满足条件的圆的直径(保留小数点后3位有效数字,四舍五入)。

        输入样例: 4

        0 0

        1 1

        3 0

        0 0.5

        输出样例: 2.236

题目1解答:

        暴力解法:遍历所有圆的半径,逐个对比找到最大值

import java.util.Scanner;
public class Main{
	public static int n;
	public static double[] x = new double[n + 10];
	public static double[] y = new double[n + 10];
	public static boolean check(double ox, double oy, double r) {
		int cnt = 0;
		for(int i = 1; i <= n; i++) {
			double dis = Math.sqrt((x[i] - ox) * (x[i] - ox) + (y[i] - oy) * (y[i] - oy));
			if(dis <= r)
				cnt++;
		}
		if(cnt == 2)
			return true;
		else
			return false;
	} 
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		double ans = 0;
		for(int i = 1; i <= n; i++) {
			x[i] = sc.nextDouble();
			y[i] = sc.nextDouble();
		}
		for(int i = 1; i <= n - 1; i++) {
			for(int j = i + 1; j <= n; j++) {
				double ox = (x[i] + x[j]) / 2;
				double oy = (y[i] + y[j]) / 2;
				double r = Math.sqrt((x[i] - ox) * (x[i] - ox) + (y[i] - oy) * (y[i] - oy));
				if(check(ox, oy, r)) {
				 	ans = Math.max(ans, r * 2);
				}
			}
		}
		System.out.printf("%.3f\n", ans);
	}
}

题目2:动态规划题   

        某游戏公司设计了一个奖励活动,给N个用户(1≤N≤10^ 7)连续编号为1到N,依据用户的编号S发放奖。

        发放奖励规则为:

                公司随机设定三个非零正整数x,y,z。

                如果S同时是x、y的倍数,奖励2张卡片;

                如果S同时是y、z的倍数, 奖励4张卡片:

                如果S同时是x、z的倍数,奖励8张卡片;

                如果S同时是x,y, z的倍数奖励10张卡片;

                其他奖励1张卡片;

        以上奖励不能同时享受。满足多个奖励条件时,以最高奖励为准。

        求任意连续的L个用户,使得这L个用户得到的奖励总和最多 ,输出奖励总和的值。

        输入说明:第一行,输入N,L,以空格隔开; (1≤L≤N≤10^7)第二行,输入x,y,z,以空格隔开; (1≤x,y,z≤L)

        输出说明:符合条件的连续L个用户的奖励总和的最大值。

        输入样例: 40 7

        3 5 2

        输出样例: 24

题目2解答:

        首先将员工编号按照游戏规则转换为获得的卡片数,用一维数组score[i]保存

        然后进行动态规划三步走:

        定义dp[]dp[i]表示前i个员工获得的卡片总数

        状态转移方程:ans =  dp[i], i l

                   ​​​​​​​        ​​​​​​​      ans = ​​​​​​​ max(ans, dp[i+ l] - dp[i]), l < i < n - l

        初始值:ans = 0

import java.util.Scanner;
public class Main{
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int l = sc.nextInt();
		int x = sc.nextInt();
		int y = sc.nextInt();
		int z = sc.nextInt();
		long[] dp = new long[n + 10];
		long[] score = new long[n + 10];
		dp[0] = 0;
		for(int i = 1; i <= n; i++) {
			int flag1, flag2, flag3, flag4;
			flag1 = flag2 = flag3 = flag4 = 0;
			if(i % x == 0 && i % y == 0) flag1 = 1;
			if(i % y == 0 && i % z == 0) flag2 = 1;
			if(i % x == 0 && i % z == 0) flag3 = 1;
			if(i % x == 0 && i % y == 0 && i % z == 0) flag4 = 1;
			if(flag4 == 1) score[i] = 10;
			else if(flag3 == 1) score[i] = 8;
			else if(flag2 == 1) score[i] = 4;
			else if(flag1 == 1) score[i] = 2;
			else score[i] = 1;
			dp[i] = dp[i - 1] + score[i];
		}
		long ans = 0;
		for(int i = 1; i <= n - l; i++) {
			ans = Math.max(ans, dp[i + l] - dp[i]);
		}
		System.out.println(ans);
	}
}

你可能感兴趣的:(科技类竞赛,java,程序设计)