2019-西工大计算机-夏令营机试代码参考

 
1. 用海伦公式求面积,先判断是不是三角形,不是三角形输出 NaN ,是三角形输出三角形 的面积,小数点后保留两位。海伦公式会给出
输入样例:2
1.0 2.0 3.0
3.0 4.0 5.0
输出样例:
NaN
6.00
判断是否成立,然后利用公式求解面积;
#include<stdio.h>
#include<math.h>
int main(){
	int n;
	scanf("%d",&n);
	while(n--){
	double a,b,c,p,area;
	scanf("%lf%lf%lf",&a,&b,&c);
	if(a+b>c&&a+c>b&&b+c>a){
			p=(a+b+c)/2;
	        area=sqrt(p*(p-a)*(p-b)*(p-c));
	        printf("%0.2lf\n",area);
	}
	else
		printf("NaN\n");
	}
	return 0;
}
2. 做一个高考倒计时器,求一年中任意两天差值,输入 N 组数据进行测试时,输出这两天之间的间隔天数,第二个日期总是在比第一个日期要大。
例如,输入:
2
2019 1 1 2019 1 2
2016 1 1 2016 3 1
输出:
2
61

主要几点:日期先后问题,闰年问题

  1. 年份相同,月份相同,天数不同,天数差值。
  2. 年份相同,月份不同;
    • 分别求出该天是本年的第几天。
    • 注意特殊月份二月,设置月份数组,设置判断闰年判断函数,闰年改变二月份数组值,平年数组不变,计算出这一天是这一年的第几天,然后求差值。
  3. 年份不同;
    • 相差一年。先判断每一年的闰年平年情况,值a:前一年全年天数减去思路2.2,值b: 后一年日期是该年的第几天。
    • 相差大于一天。在1的基础上,然后将中间相差全年的天数相加(时刻注意判断闰年和平年)。
 
#include<stdio.h>
int date(int n1,int y1,int r1,int n2,int y2,int r2);
int run_or_ping(int x);
inline int yue_r(int n,int y);
int main()
{
	int n1,y1,r1,n2,y2,r2;
	printf("请输入第一个较小的年月日,用空格分开\n");
	scanf("%04d%02d%02d",&n1,&y1,&r1);
	printf("请输入第二个较大的年月日,用空格分开\n");
	scanf("%04d%02d%02d",&n2,&y2,&r2);
 
	date(n1,y1,r1,n2,y2,r2);
	return 0;
}
int date(int n1,int y1,int r1,int n2,int y2,int r2)
{
	int i,j,sum=0,sum1=0;
 
	for(i=n1;i!=n2;i++)
	{
		if(run_or_ping(i)==1)
			sum=sum+366;
		else sum=sum+365;
	}
	if(y1<y2)
		for(j=y1;j!=y2;j++)
		{
			sum=sum+yue_r(n2,j);
		}
	else
	{
		for(j=y2;j!=y1;j++)
			sum1=sum1+yue_r(n2,j);
		sum=sum-sum1;
	}
 
	sum=sum+r2-r1+1;
	printf("%04d.%02d.%02d~%04d.%02d.%02d相差%d天",n1,y1,r1,n2,y2,r2,sum);
	return 0;
}
int run_or_ping(int x)
{
	if(x%4==0)
		{
			if(x%100==0)
				if(x%400!=0)
					return 0;
			return 1;
		}
	else return 0;
}
int yue_r(int n,int y)
{
	if(y==2)
	{
		if(run_or_ping(n)==1)
			return 29;
		else return 28;
	}
	else if(y==4||y==6||y==9||y==11)
		return 30;
	else return 31;
}
/**
日期格式规定为YYYYMMDD,例如20200709
(1)输入两个日期
(2)以小的日期为底,每次加一天,直到与大的日期相等即可
(2.1)增加一天后,月份,年份都可能会随之变化。针对闰年平年以及大小月天数都一样,采用一个12*2的二维数组列出12月的润平年的天数。
(2.2)当达到月份的天数时,月份加1
(2.3)当达到12个月时,年份加1
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
bool isLeap(int year) {
	return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
}
int main() {
	//定义好平年和闰年每月的天数
	int monthDays[13][2] = {
		{0,0},{31,31},{28,29},{30,30},{31,31},{30,30},
		{31,31},{30,30},{31,31},{30,30},{31,31},{30,30},
		{31,31}
	};
	int time1, year1, month1, days1;
	int time2, year2, month2, days2;
	int numbers =1;
	// 输入两个日期
	cout << "输入两个日期,空格分隔";
	cin >> time1 >> time2;
	if (time1>time2){
		int temp = time1;
		time1 = time2;
		time2 = temp;

	}
	//拆解日期,分为年,月,号
	year1 = time1 / 10000; month1 = time1 / 100 % 100; days1 = time1 % 100;
	year2 = time2 / 10000; month2 = time2 / 100 % 100; days2 = time2 % 100;
	//第一个日期 累加到 第二个日期
	while (year1 < year2 || month1 < month2 || days1 < days2) {
		days1++;// 在第一个日期基础上  加一天
		//加一天后,相应的月,年可能也要做一定的变化
		if (days1 == monthDays[month1][isLeap(year1)]+1) {//当前号超过当前月最高天数:月份加1,号变成下月的1号
			month1++;
			days1 = 1;
		}
		if (month1 == 13) {//月份超过12个月 :年份加1,月份变成下年的1月
			year1++;
			month1 = 1;
		}
		numbers++;
	}
	cout << numbers << endl;
	return 0;
}

 

3. 有一对兔子,从出生后第 3 个月起每个月都生一对兔子,满足 Fibonacci 数列 f(n)=f(n-1)+f(n-2), 1 1 2 3 5 8 13 21 34 、……小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,输入第 N 个月,输出该月有多少对兔子?
输入样例:
2
3
5
输出样例:
1
2
5

四种解法:递归+动态规划+优化求解+矩阵乘法

解法1:递归

斐波那契数列的标准公式为:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)

根据公式可以直接写出:

int fibonacci1(int n){
		if(n<2){
			return n;
		}
		else{
			return fibonacci1(n-1)+fibonacci1(n-2);
		}
	}
时间复杂度:O(2^n)
空间复杂度:O(1)

解法2:动态规划

递归会重复计算大量相同数据,我们用个数组把结果存起来

int Fibonacci(int n) {
    vector<int> dp(n+1, 0);
        dp[1] = 1;
        for (int i=2; i<=n; ++i) {
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];
}

 

解法3:优化存储

优化:发现计算f[5]的时候只用到了f[4]和f[3], 没有用到f[2]...f[0],所以保存f[2]..f[0]是浪费了空间。只需要用3个变量即可

int Fibonacci(int n) {
     if (n == 0 || n == 1) return n;
        int a = 0, b = 1, c;
        for (int i=2; i<=n; ++i) {
            c = a + b;
            a = b;
            b = c;
        }
        return c;
}
时间复杂度:O(n)
空间复杂度:O(1)

 

继续优化:两个变量

 //非递归的方法 O(N)
	public static int fibonacci2(int n){
		if(n<2){
			return n;
		}
		int a=0,b=1;
		for(int i=2;i<=n;i++){
			b=b+a;//
			a=b-a;//
		}
		return b;
	}
 时间复杂度:O(n)
 空间复杂度:O(1)

解法4:矩阵乘法

 

4. 求阶乘,求一个数的阶乘,这个数是 1-100 中的一个,提示 32 位会溢出,但是要求输出的结果要保证正确,不能溢出。
输入样例: 25
20
输出样例: 2
120
2432902008176640000
    int getFactorial1(int n){// 递归
		if(n==1){
			return 1;
		}
		return n*getFactorial1(n-1);
	}
/*-------------------------------------------------------------*/
	int getFactorial2(int n){// 循环
		int result=1;
		for(int i=1;i<=n;i++){
			result=result*i;
		}
		return result;
	}

5.给定一个括号’(’,’)’,’{’,’}’,’[’,’]’的字符串,判断字符串是否有效。有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 注意空字符串可被认为是有效字符串,括号里可以包括其他一些字符。
输入样例:

{a}[b](d)

{[}]

输出样例:

Yes

no

用栈实现括号匹配:

依次扫描所有字符,遇到左括号入栈,遇到右括号则弹出栈顶元素检查是否匹配。

匹配失败情况:

①左括号多

②右括号多

③左右括号不匹配

public static boolean isValid1(String s){
		Stack<Character> stack=new Stack<>();
		if(s==null || s=="")
			return false;
		for(int i=0;i<s.length();i++){
			char c=s.charAt(i);
			if(c=='(' || c=='[' || c=='{' ){
				stack.push(c);
			}
            else if(c!=')' && c!=']' && c!='}'){
                continue;
            }
			else{
				if(stack.isEmpty())
					return false;
				char topChar=stack.pop();
				if(c==')' && topChar!='(')
					return false;
				if(c==']' && topChar!='[')
					return false;
				if(c=='}' && topChar!='{')
					return false;
			}
		}
		//如果遍历完字符串后,栈不为空,则说明括号不匹配
		return stack.isEmpty();
	}
	
	public static void main(String[] args){
		Scanner sc=new Scanner(System.in);
		String str=sc.nextLine();
		if(isValid1(str)){
			System.out.println("匹配成功!") ;
		}
		else{
			System.out.println(" 匹配失败 ");
		}
	}

首先如果字符串s的长度为奇数的话,直接不符合
这题可以看做是消消乐游戏,匹配则消除,直到全部消除则说明符合条件,没有消除完则说明不符合条件,所以直观的思路就可以使用一个栈来实现。
另外,如何知道消除规则,可以使用一个哈希表来保存消除对应关系。有这样的思路就可以编码了,遍历字符串,如果是左括号(哈希表的key),入栈,如果是右括号,出栈,但是出栈有一个前提是出栈元素能够和当前遍历符号匹配消除,否则直接不符合

class Solution {
    public boolean isValid(String s) {
        if (s == null || s.length() % 2 != 0) {
            return false;
        }
        //使用一个哈希表保存括号对应关系
        Map<Character, Character> map = new HashMap<>();
        map.put('(', ')');
        map.put('[', ']');
        map.put('{', '}');
        //遍历字符串,入栈,遇到对应括号,则出栈
        Deque<Character> stack = new ArrayDeque<>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (map.containsKey(c)) {//如果是左括号,入栈
                stack.push(c);
            } else {//右括号
                //如果当前栈已经是空的,或者栈头元素与该右括号c不匹配,直接返回false
                if (stack.isEmpty() || map.get(stack.peek()) != c) {
                    return false;
                }
                stack.pop();
            }
        }
        return stack.isEmpty();
    }
}
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值