2022计算机能力挑战赛决赛JAVA组题解

A题

题目描述

在这里插入图片描述

思路

简单DP,背包模型,DP分析如下
在这里插入图片描述

参考代码

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
	static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static int N=60,M=1100;
	static int w[]=new int[N];
	static int f[][]=new int[N][M];
	static int m,n;
	
	public static void main(String[] args) throws Exception{
		String[] inn=br.readLine().split(" ");
		m=Integer.parseInt(inn[0]);
		n=Integer.parseInt(inn[1]);
		inn=br.readLine().split(" ");
		for(int i=1;i<=n;i++) w[i]=Integer.parseInt(inn[i-1]);
		f[0][0]=1; // 边界条件 考虑完0个物品且当前天平上重量为0的方案数为1
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<=m;j++) 
			{
				f[i][j]=f[i-1][j];
				if(j>=w[i]) f[i][j]+=f[i-1][j-w[i]];
			}
		}
		System.out.println(f[n][m]);  
	}
}

滚动数组优化


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
	static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static int N=60,M=1100;
	static int w[]=new int[N];
	static int f[]=new int[M];
	static int m,n;
	
	public static void main(String[] args) throws Exception{
		String[] inn=br.readLine().split(" ");
		m=Integer.parseInt(inn[0]);
		n=Integer.parseInt(inn[1]);
		inn=br.readLine().split(" ");
		for(int i=1;i<=n;i++) w[i]=Integer.parseInt(inn[i-1]);
		f[0]=1;
		for(int i=1;i<=n;i++) 
		{
			for(int j=m;j>=w[i];j--) f[j]+=f[j-w[i]];
		}
		System.out.println(f[m]);
	}
}

B题

题目描述

在这里插入图片描述

思路

简单DP,典型的背包模型,DP分析如下
在这里插入图片描述

参考代码


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
	static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static int N=110,M=5500;
	static int w[]=new int[N];
	static int p[]=new int[N];
	static int f[][]=new int[N][M];
	static int m,n;
	
	public static void main(String[] args) throws Exception{
		String[] inn=br.readLine().split(" ");
		m=Integer.parseInt(inn[0]);
		n=Integer.parseInt(inn[1]);
		for(int i=1;i<=n;i++) 
		{
			inn=br.readLine().split(" ");
			w[i]=Integer.parseInt(inn[0]);
			p[i]=Integer.parseInt(inn[1]);
			// 题目给的是单价,由于货物要么全部装要么不装,所以价值为单价*总数量
			w[i]=w[i]*p[i]; 
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<=m;j++) 
			{
				f[i][j]=f[i-1][j];
				if(j>=w[i]) f[i][j]=Math.max(f[i][j],f[i-1][j-w[i]]+p[i]);
			}
		}
		System.out.println(f[n][m]);
	}
}

滚动数组优化


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
	static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static int N=110,M=5500;
	static int w[]=new int[N];
	static int p[]=new int[N];
	static int f[]=new int[M];
	static int m,n;
	
	public static void main(String[] args) throws Exception{
		String[] inn=br.readLine().split(" ");
		m=Integer.parseInt(inn[0]);
		n=Integer.parseInt(inn[1]);
		for(int i=1;i<=n;i++) 
		{
			inn=br.readLine().split(" ");
			w[i]=Integer.parseInt(inn[0]);
			p[i]=Integer.parseInt(inn[1]);
			
			// 题目给的是单价,由于货物要么全部装要么不装,所以价值为单价*总数量
			w[i]=w[i]*p[i];
		}
		for(int i=1;i<=n;i++) 
		{
			for(int j=m;j>=w[i];j--) f[j]=Math.max(f[j],f[j-w[i]]+p[i]);
		}
		System.out.println(f[m]);
	}
}

C题

题目描述

在这里插入图片描述

思路

模拟

利用日期类或Calendar类计算出给定天数与2022年10月1日之间差的总天数与7的余数,分别判断对应的情况,输入对应的运动类型即可

参考代码


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Calendar;

public class Main {
	static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	
	public static void main(String[] args) throws Exception{
		String[] inn=br.readLine().split("-");
		Calendar cal=Calendar.getInstance();
		cal.set(Calendar.YEAR, 2022);
		cal.set(Calendar.MONTH,10);
		cal.set(Calendar.DAY_OF_MONTH, 1);
		long days1=cal.getTimeInMillis()/1000/60/60/24;
		int year=Integer.parseInt(inn[0]);
		int month=Integer.parseInt(inn[1]);
		int day=Integer.parseInt(inn[2]);
		Calendar cal_in=Calendar.getInstance();
		cal_in.set(Calendar.YEAR,year);
		cal_in.set(Calendar.MONTH,month);
		cal_in.set(Calendar.DAY_OF_MONTH,day);
		long days2=cal_in.getTimeInMillis()/1000/60/60/24;
		long ans=days2-days1;
		ans%=7;
		
		// 对7求余之后,0~6为一循环,所以0~2天为长跑,3~5天为爬上,6为徒步远足
		if(ans>=0 && ans<3) System.out.println("长跑");
		else if(ans>=3 && ans<6) System.out.println("爬山");
		else if(ans>=6) System.out.println("徒步远足");
	}
}

D题

题目描述在这里插入图片描述

思路

模拟+哈希

可以先将对应类型的字符哈希成1~4之间的数字,这样就可以利用数组下标来存储对应种类物品的总数量和价值,最终根据题目的要求打折即可

参考代码


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.HashMap;

// 商品类
class good
{
	String type;
	int price;
	int num;
	
	public good(String type, int price, int num) {
		super();
		this.type = type;
		this.price = price;
		this.num = num;
	}
}

public class Main {
	static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static int N=110;
	static good goods[]=new good[N];
	static int cnt[]=new int[5];
	static double sum[]=new double[5];
	static int idx;
	static int n;
	static int score;
	
	public static void main(String[] args) throws Exception{
		HashMap<String,Integer> hm=new HashMap<>();
		n=Integer.parseInt(br.readLine());
		
		// 将对应类型的字符串进行哈希,以便通过数组下标访问
		hm.put("W",1);
		hm.put("H",2);
		hm.put("B",3);
		hm.put("E",4);
		for(int i=1;i<=n;i++) 
		{
			String[] inn=br.readLine().split(" ");
			String type=inn[0];
			int price=Integer.parseInt(inn[1]);
			int num=Integer.parseInt(inn[2]);
			goods[i]=new good(type,price,num);
		}
		
		score=Integer.parseInt(br.readLine());
		
		for(int i=1;i<=n;i++) 
		{
			int index=hm.get(goods[i].type);
			cnt[index]+=goods[i].num;
			sum[index]+=goods[i].price*goods[i].num;
		}
		
		double ans=0;
		for(int i=1;i<=4;i++) 
		{
			sum[i]*=0.95;
			if(cnt[i]>=5) sum[i]*=0.8;
			else if(cnt[i]>=3) sum[i]*=0.9;
			ans+=sum[i];
		}
		if(score>=5000 && score<=10000) ans*=0.95;
		else if(score>10000) ans*=0.9;
		
		//保留一位小数
		DecimalFormat df=new DecimalFormat("0.0");
		System.out.println(df.format(ans));
	}
}

E题

题目描述在这里插入图片描述

思路

贪心

该题是一道多机调度问题模型的应用。我们想要占用的功能厅的时间最短,需要采取的贪心策略为每次将当前任务中所需时间最长的任务分配给最先空闲的多功能厅。但这题给定的节目编号是字符串,所以我们需要额外定义一个节目类来存储每个节目,同时还需要为每个多功能厅定义一个数组来存储每个多功能厅安排过的节目。最终将所有的节目按字典序排序输出即可。

参考代码


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;

// 节目类
class show
{
	String name;
	int time;
	int idx; // 当前的节目安排在哪个多功能厅
	int num; // 当前节目在所安排多功能厅中的第几个节目
	
	public show(String name, int time) {
		super();
		this.name = name;
		this.time = time;
	}
}

public class Main {
	static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static int N=110;
	static int M=15;
	static show shows[]=new show[N];
	static int cnt[]=new int[M]; // 存储每个多功能厅所安排的节目数
	static int t[]=new int[M];  // 存储每个多功能厅最早空闲的时间
	static int n,m;
	
	public static void main(String[] args) throws Exception{
		String[] inn=br.readLine().split(" ");
		n=Integer.parseInt(inn[0]);
		m=Integer.parseInt(inn[1]);
		for(int i=1;i<=n;i++) 
		{
			inn=br.readLine().split(":");
			String name=inn[0];
			int time=Integer.parseInt(inn[1]);
			shows[i]=new show(name,time);
		}
		
		// 将所有节目按所需时间降序排序
		Arrays.sort(shows,1,n+1,new Comparator<show>() {
			@Override
			public int compare(show o1, show o2) {
				// TODO Auto-generated method stub
				return o2.time-o1.time;
			}
		});
		
		for(int i=1;i<=n;i++) 
		{
			int pos=find();
			t[pos]+=shows[i].time;
			cnt[pos]++;
			shows[i].idx=pos;
			shows[i].num=cnt[pos];
		}
		
		Arrays.sort(shows,1,n+1,new Comparator<show>() {
			@Override
			public int compare(show o1, show o2) {
				// TODO Auto-generated method stub
				return o1.name.compareTo(o2.name);
			}
		});
		
		int ans=0;
		for(int i=1;i<=m;i++) ans=Math.max(ans,t[i]);
		System.out.println(ans);
		
		for(int i=1;i<=n;i++) System.out.println(shows[i].name+":"+shows[i].idx+"-"+shows[i].num);
	}

	// 找到最小空闲的多功能厅的编号
	private static int find() {
		// TODO Auto-generated method stub
		int minn=100;
		int mini=-1;
		for(int i=1;i<=m;i++) 
		{
			if(t[i]<minn) 
			{
				minn=t[i];
				mini=i;
			}
		}
		return mini;
	}
	
}

总结

总体来说,此次的Java组决赛题目思维难度不大,主要考验代码能力。整体的题目难度中等偏简单。希望我的题解能帮助到有需要的人

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值