CSP第十五次题目(前四题)附有c++和java代码

1.小明上学

试题编号: 1
试题名称: 小明上学
时间限制: 1.0s
内存限制: 512.0MB
问题描述: 题目背景
  小明是汉东省政法大学附属中学的一名学生,他每天都要骑自行车往返于家和学校。为了能尽可能充足地睡眠,他希望能够预计自己上学所需要的时间。他上学需要经过数段道路,相邻两段道路之间设有至多一盏红绿灯。
  京州市的红绿灯是这样工作的:每盏红绿灯有红、黄、绿三盏灯和一个能够显示倒计时的显示牌。假设红绿灯被设定为红灯 r 秒,黄灯 y 秒,绿灯 g 秒,那么从 0 时刻起,[0,r) 秒内亮红灯,车辆不许通过;[r, r+g) 秒内亮绿灯,车辆允许通过;[r+g, r+g+y) 秒内亮黄灯,车辆不许通过,然后依次循环。倒计时的显示牌上显示的数字 l(l > 0)是指距离下一次信号灯变化的秒数。
问题描述
  一次上学的路上,小明记录下了经过每段路的时间,和各个红绿灯在小明到达路口时的颜色和倒计时秒数。希望你帮忙计算此次小明上学所用的时间。
输入格式
  输入的第一行包含空格分隔的三个正整数 r、y、g,表示红绿灯的设置。这三个数均不超过 106。
  输入的第二行包含一个正整数 n(n ≤ 100),表示小明总共经过的道路段数和看到的红绿灯数目。
  接下来的 n 行,每行包含空格分隔的两个整数 k、t。k=0 表示经过了一段道路,耗时 t 秒,此处 t 不超过 106;k=1、2、3 时,分别表示看到了一个红灯、黄灯、绿灯,且倒计时显示牌上显示的数字是 t,此处 t 分别不会超过 r、y、g。
输出格式
  输出一个数字,表示此次小明上学所用的时间。
样例输入
30 3 30
8
0 10
1 5
0 11
2 2
0 6
0 3
3 10
0 3
样例输出
70
样例说明
  小明先经过第一段道路,用时 10 秒,然后等待 5 秒的红灯,再经过第二段道路,用时 11 秒,然后等待 2 秒的黄灯和 30 秒的红灯,再经过第三段、第四段道路,分别用时6、3秒,然后通过绿灯,再经过最后一段道路,用时 3 秒。共计 10 + 5 + 11 + 2 + 30 + 6 + 3 + 3=70 秒。
评测用例规模与约定
  测试点 1, 2 中不存在任何信号灯。
  测试点 3, 4 中所有的信号灯在被观察时均为绿灯。
  测试点 5, 6 中所有的信号灯在被观察时均为红灯。
  测试点 7, 8 中所有的信号灯在被观察时均为黄灯。
  测试点 9, 10 中将出现各种可能的情况。

c++代码(100分)

#include<iostream>
using namespace std;
int main()
{
	int i,red,yellow,green,n,a,b,sum=0;
	cin>>red>>yellow>>green;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>a>>b;
		if(a==0)
			sum=sum+b;
		else if(a==1)
			sum=sum+b;
		else if(a==2)
			sum=sum+red+b;
	}
	cout<<sum;

	return 0;
}

java代码(100分)

package csp15;
import java.util.*;
public class Main {
public static void main(String[] args){
	int i,red,yellow,green,n,a,b,sum=0;
	Scanner input=new Scanner(System.in);
	red = input.nextInt();
	yellow = input.nextInt();
	green = input.nextInt();
	n=input.nextInt();
	for(i=1;i<=n;i++)
	{
		a=input.nextInt();
		b=input.nextInt();
		if(a==0)
			sum=sum+b;
		else if(a==1)
			sum=sum+b;
		else if(a==2)
			sum=sum+red+b;
	}
	System.out.println(sum);
	input.close();
}
}

2.小明放学

试题编号: 2
试题名称: 小明放学
时间限制: 1.0s
内存限制: 512.0MB
问题描述: 题目背景
  汉东省政法大学附属中学所在的光明区最近实施了名为“智慧光明”的智慧城市项目。具体到交通领域,通过“智慧光明”终端,可以看到光明区所有红绿灯此时此刻的状态。小明的学校也安装了“智慧光明”终端,小明想利用这个终端给出的信息,估算自己放学回到家的时间。
问题描述
  一次放学的时候,小明已经规划好了自己回家的路线,并且能够预测经过各个路段的时间。同时,小明通过学校里安装的“智慧光明”终端,看到了出发时刻路上经过的所有红绿灯的指示状态。请帮忙计算小明此次回家所需要的时间。
输入格式
  输入的第一行包含空格分隔的三个正整数 r、y、g,表示红绿灯的设置。这三个数均不超过 106。
  输入的第二行包含一个正整数 n,表示小明总共经过的道路段数和路过的红绿灯数目。
  接下来的 n 行,每行包含空格分隔的两个整数 k、t。k=0 表示经过了一段道路,将会耗时 t 秒,此处 t 不超过 106;k=1、2、3 时,分别表示出发时刻,此处的红绿灯状态是红灯、黄灯、绿灯,且倒计时显示牌上显示的数字是 t,此处 t 分别不会超过 r、y、g。
输出格式
  输出一个数字,表示此次小明放学回家所用的时间。
样例输入
30 3 30
8
0 10
1 5
0 11
2 2
0 6
0 3
3 10
0 3
样例输出
46
样例说明
  小明先经过第一段路,用时 10 秒。第一盏红绿灯出发时是红灯,还剩 5 秒;小明到达路口时,这个红绿灯已经变为绿灯,不用等待直接通过。接下来经过第二段路,用时 11 秒。第二盏红绿灯出发时是黄灯,还剩两秒;小明到达路口时,这个红绿灯已经变为红灯,还剩 11 秒。接下来经过第三、第四段路,用时 9 秒。第三盏红绿灯出发时是绿灯,还剩 10 秒;小明到达路口时,这个红绿灯已经变为红灯,还剩两秒。接下来经过最后一段路,用时 3 秒。共计 10+11+11+9+2+3 = 46 秒。
评测用例规模与约定
  有些测试点具有特殊的性质:
  * 前 2 个测试点中不存在任何信号灯。
  测试点的输入数据规模:
  * 前 6 个测试点保证 n ≤ 103。
  * 所有测试点保证 n ≤ 105。

c++代码(100分)

#include<iostream>
using namespace std;
int main()
{
	long long int i,red,yellow,green,color,n,a,b,sum=0;
	cin>>red>>yellow>>green;
	color=red+yellow+green;
	cin>>n;
	for(i=1;i<=n;i++)//红->绿->黄->红
	{
		cin>>a>>b;
		if(a==0)
			sum=sum+b;
		else if(a==1)//红灯
			if(sum-b>0)
			{
				if((sum-b)%color>=green&&(sum-b)%color<(green+yellow))//处于黄灯
					sum=sum+red+(yellow-((sum-b)%color-green));
				if((sum-b)%color>=(green+yellow)&&(sum-b)%color<color)//处于红灯
					sum=sum+(red-((sum-b)%color-green-yellow));
			}
			else sum=sum+b-sum;
		else if(a==2)//黄灯
			if(sum-b>0)
			{
				if((sum-b)%color>=0&&(sum-b)%color<red)//处于红灯
					sum=sum+(red-(sum-b)%color);
				if((sum-b)%color>=(red+green)&&(sum-b)%color<color)//处于黄灯
					sum=sum+red+(yellow-((sum-b)%color-green-red));
			}
			else sum=sum+b-sum+red;
		else if(a==3)//绿灯
			if(sum-b>0)
			{
				if((sum-b)%color>=0&&(sum-b)%color<yellow)//处于黄灯
					sum=sum+red+(yellow-(sum-b)%color);
				if((sum-b)%color>=yellow&&(sum-b)%color<(yellow+red))//处于红灯
					sum=sum+(red-((sum-b)%color-yellow));
			}
			else sum=sum;
		//cout<<sum<<endl;
			
	}
	cout<<sum;
	return 0;
}

java代码(100分)

package csp15;

import java.util.Scanner;

public class Main {
public static void main(String[] args){
	long i,red,yellow,green,color,n,a,b,sum=0;
	Scanner input=new Scanner(System.in);
	red=input.nextInt();
	yellow=input.nextInt();
	green=input.nextInt();
	
	color=red+yellow+green;
	n=input.nextInt();
	for(i=1;i<=n;i++)//红->绿->黄->红
	{
		a=input.nextInt();
		b=input.nextInt();
		if(a==0)
			sum=sum+b;
		else if(a==1)//红灯
			if(sum-b>0)
			{
				if((sum-b)%color>=green&&(sum-b)%color<(green+yellow))//处于黄灯
					sum=sum+red+(yellow-((sum-b)%color-green));
				if((sum-b)%color>=(green+yellow)&&(sum-b)%color<color)//处于红灯
					sum=sum+(red-((sum-b)%color-green-yellow));
			}
			else sum=sum+b-sum;
		else if(a==2)//黄灯
			if(sum-b>0)
			{
				if((sum-b)%color>=0&&(sum-b)%color<red)//处于红灯
					sum=sum+(red-(sum-b)%color);
				if((sum-b)%color>=(red+green)&&(sum-b)%color<color)//处于黄灯
					sum=sum+red+(yellow-((sum-b)%color-green-red));
			}
			else sum=sum+b-sum+red;
		else if(a==3)//绿灯
			if(sum-b>0)
			{
				if((sum-b)%color>=0&&(sum-b)%color<yellow)//处于黄灯
					sum=sum+red+(yellow-(sum-b)%color);
				if((sum-b)%color>=yellow&&(sum-b)%color<(yellow+red))//处于红灯
					sum=sum+(red-((sum-b)%color-yellow));
			}
			//else sum=sum;
		//cout<<sum<<endl;
			
	}
	System.out.println(sum);
	input.close();
}
}

3.CIDR合并(100分)

试题编号: 3
试题名称: CIDR合并
时间限制: 1.0s
内存限制: 512.0MB
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
样例输入
2
1
2
样例输出
1.0.0.0/8
2.0.0.0/8
样例输入
2
10/9
10.128/9
样例输出
10.0.0.0/8
样例输入
2
0/1
128/1
样例输出
0.0.0.0/0
在这里插入图片描述
在这里插入图片描述

c++代码(100分)

#include<iostream>
#include<list>
#include<string>
 
using namespace std;
 
struct IP{
	string ip;//ip地址 
	int len;//前缀长度 
	IP(){}
	//以IP地址为第一关键字,前缀长度为第二关键字,从小到大排序
	IP(string ip,int len):ip(ip),len(len){}
    bool operator <(const IP &a)const
    {
    	return ip==a.ip?(len<a.len):(ip<a.ip);
	}
};
 
list<IP>ipAddress;
 
//将整数n(0<=n<256)化成二进制数 
string itos(int  n)
{
	string res="00000000";
	int k=7;
	while(n)
	{
		res[k--]=n%2+'0';
		n/=2;
	}
	return res;
}
 
//读取ip前缀 
void read()
{
	string ip="";
	char ch;
	int len=0,k=0,val=0;//k记录小数点的数量 
	bool flag=false;
	while((ch=getchar())!='\n')//读入'\n'退出 
	{
		if(ch=='.')//读入小数点 
		{
			k++;
			ip+=itos(val);
			val=0; 
		}
		else if(ch=='/')
		{
			ip+=itos(val);
			val=0;
			flag=true;
		}
		else
		  val=val*10+ch-'0';
	}
	len=(flag?val:(k+1)*8);//如果flag=true len就等于val,否则就是省略长度型 
	if(!flag) ip+=itos(val);//flag=false,表示是省略后缀型,那么val就是ip前缀的一部分 
	while(k<3)//补零
	{
		ip+=itos(0);
		k++;
	}
	ipAddress.insert(ipAddress.end(),IP(ip,len));//将元素插入list中 
}
 
int main()
{
	int n,i;
	scanf("%d",&n);
	getchar();//读取空白符 
	for(i=1;i<=n;i++)//读入n个ip前缀 
	  read();
	ipAddress.sort();//第一步:排序 
	list<IP>::iterator cur;
	list<IP>::iterator next;
	for(cur=ipAddress.begin();cur!=ipAddress.end();)//第二步:从小到大合并 end()指向最后一个元素的下一个元素,.bengin()返回当前vector容器中起始元素的引用
	{
		next=cur;
		next++;
		if(next==ipAddress.end()) break;//如果cur已经是最后一个元素了就退出 

		for(i=0;i<cur->len;i++)
		  if(cur->ip[i]!=next->ip[i])
		    break;

		if(i==cur->len)//如果next是cur的子集,就删除next 
		  ipAddress.erase(next);//erase()删除next一行
		else 
		  cur++;//查看下一个元素 
	}
	for(cur=ipAddress.begin();cur!=ipAddress.end();)//第三步:统计合并    10/9     10.128/9

	{
		next=cur;
		next++;
		if(next==ipAddress.end()) break;
		if(cur->len==next->len&&cur->len>0&&cur->ip[cur->len-1]=='0')
		{
			for(i=0;i<cur->len-1;i++)
			  if(cur->ip[i]!=next->ip[i])
			    break;
			if(i==cur->len-1)
			{
				ipAddress.erase(next);
				cur->len-=1;
				if(cur!=ipAddress.begin())//如果cur的前面还有元素,则让cur-- 
				{
					cur--;
					continue;
				}
			}
		}
		cur++;//考虑下一个元素 
	}
	//输出 
	for(cur=ipAddress.begin();cur!=ipAddress.end();cur++)
	{
		for(i=7;i<32;i+=8)
		{
			int temp=0;
			for(int j=i-7;j<=i;j++)
			  temp=temp*2+cur->ip[j]-'0';//注意权值为2 
			printf("%d",temp);
			if(i!=31) printf(".");
		}
		printf("/%d\n",cur->len);
	}
	return 0;
}

java代码(60分)

这个是根据上面100分的c++代码改的,可只有60分哈

package csp15;
import java.util.Scanner;
class IP {
	String ip;//地址 
	int len;//前缀长度 
	IP(){}
	//以IP地址为第一关键字,前缀长度为第二关键字,从小到大排序
}
public class Main {
	public static String itos(int n){
		char []str =new char[8];
		for(int i=0;i<8;i++){
			str[i]='0';
		}
		int k=7;
		while(n!=0){
			if(n%2==0){
				str[k--]='0';
			}
			else  
				str[k--]='1';
			n = n/2;
		}
		String Str=new String(str);
		return Str;	
	}
	public static IP read(String Str){
		String ip = "";
		char ch;
		IP a=new IP();
		int k=0,val=0;//k记录小数点的数量 
		boolean flag=false;
		int n=Str.length();
		for(int i=0;i<n;i++)//读入'\n'退出 
		{
			ch=Str.charAt(i);
			if(ch=='.')//读入小数点 
			{
				k++;
				ip+=itos(val);
				val=0; 
			}
			else if(ch=='/')
			{
				ip+=itos(val);
				val=0;
				flag=true;
			}
			else
			  val=val*10+ch-'0';
		}
		int len;
		if(flag==true){
			len=val;//如果flag=true len就等于val,否则就是省略长度型 
		}
		else
			len=(k+1)*8;
		if(!flag) ip+=itos(val);//flag=false,表示是省略后缀型,那么val就是ip前缀的一部分 
		while(k<3)//补零
		{
			ip+=itos(0);
			k++;
		}
		a.ip=ip;
		a.len=len;
		return a;
	}
	public static IP[] sort1(IP[] a,int n){
		String temp;
		int lens;
		for(int i=0;i<n-1;i++)
			for(int j=0;j<n-i-1;j++){
				if(a[j].ip.compareTo(a[j+1].ip)==1){
					temp=a[j].ip;
					lens=a[j].len;
					a[j].ip=a[j+1].ip;
					a[j].len=a[j+1].len;
					a[j+1].ip=temp;
					a[j+1].len=lens;
				}
				else if(a[j].ip.compareTo(a[j+1].ip)==0){
					if(a[j].len>a[j+1].len){
						lens=a[j].len;
						a[j].len=a[j+1].len;
						a[j+1].len=lens;
					}
				}
				
			}
		return a;
	}
	public static void main(String[] args){
		int n,i,k;
		Scanner input=new Scanner(System.in);
		n=input.nextInt();
		IP[] IPaddress=new IP[10000];
		IP[] IPaddress1=new IP[10000];
		for(i=0;i<n;i++){
			IPaddress[i]=read(input.next());
		}
		IPaddress1=sort1(IPaddress,n);
		for(i=0;i<n;){//第二步:从小到大合并
			int j=i;
			j++;
			if(j==n){
				break;
			}
			for(k=0;k<IPaddress1[i].len;k++){
				if(IPaddress1[i].ip.charAt(k)!=IPaddress1[j].ip.charAt(k))
					break;
			}
			if(k==IPaddress1[i].len){
				for(int x=j;x<n-1;x++){
					IPaddress1[j].ip=IPaddress1[j+1].ip;
					IPaddress1[j].len=IPaddress1[j+1].len;
				}
				n--;
			}
			else i++;
		}
		for(i=0;i<n;){//同级合并
			int j = i;
			j++;
			if(j==n){
				break;
			}
			if(IPaddress1[i].len==IPaddress1[j].len&&IPaddress1[i].len>0&&IPaddress1[i].ip.charAt(IPaddress1[i].len-1)=='0'){
				for(k=0;k<(IPaddress1[i].len-1);k++){
					if(IPaddress1[i].ip.charAt(k)!=IPaddress1[j].ip.charAt(k)){
						break;
					}
				}
				if(k==IPaddress1[i].len-1){
					for(int x=j;x<n-1;x++){
						IPaddress1[j].ip=IPaddress1[j+1].ip;
						IPaddress1[j].len=IPaddress1[j+1].len;
					}
					n--;
					IPaddress1[i].len-=1;
					if(i!=0){
						i--;
						continue;
					}
				}
			}
			i++;
		}
		for(i=0;i<n;i++){
			for(int j=7;j<32;j+=8){
				int temp=0;
				for(k=j-7;k<=j;k++){
					if(IPaddress1[i].ip.charAt(k)=='1')
						temp=temp*2+1;
					else
						temp=temp*2;
				}
				System.out.print(temp);
				if(j!=31)
					System.out.print(".");
			}
			System.out.println("/"+IPaddress1[i].len);
		}
		/*
		for(i=0;i<n;i++){
			System.out.println(IPaddress1[i].ip);
			System.out.println(IPaddress1[i].len);
		}
		*/
		input.close();
	}
}
/*
2
10/9
10.128/9
*/


java代码(100分)

转载JAVA代码的博客(我写的没有满分,借鉴一下别人的)
https://blog.csdn.net/xuzonghao

import java.io.*;
import java.util.*;
import java.lang.*;
 
 
class prefix implements Comparable<prefix>{
	public int[] ip;
	public int len;
	public prefix(int[] ip,int len) {
		this.ip = ip;
		this.len = len;
	}
	public int compareTo(prefix x) {
		for(int i = 0; i < 4; i++) {
			if(this.ip[i] != x.ip[i])
				return this.ip[i] - x.ip[i];
		}
		return this.len - x.len;
	}
}
 
 
class Reader {
    static BufferedReader reader;
    static StringTokenizer tokenizer;
 
    /**
     * call this method to initialize reader for InputStream
     */
    static void init(InputStream input) {
        reader = new BufferedReader(
                new InputStreamReader(input));
        tokenizer = new StringTokenizer("");
    }
 
    /**
     * get next word
     */
    static String next() throws IOException {
        while (!tokenizer.hasMoreTokens()) {
            //TODO add check for eof if necessary
            tokenizer = new StringTokenizer(
                    reader.readLine());
        }
        return tokenizer.nextToken();
    }
 
    static int nextInt() throws IOException {
        return Integer.parseInt(next());
    }
 
    static double nextDouble() throws IOException {
        return Double.parseDouble(next());
    }
}
 
public class Main {
 
	public static void main(String[] args) throws IOException {
		
//		Scanner in = new Scanner(System.in);
		
//		int n = Integer.parseInt(in.nextLine());
		Reader.init(System.in);
		int n = Reader.nextInt();
		
		List<prefix> list = new ArrayList<prefix>(); 
		
		
		//读入并转换成prefix类
		for(int d = 0;d<n;d++) {
			
//			String ip = in.nextLine();
			String ip = Reader.next();
			//构建prefix对象
			int[] Ip = new int[4];
			int len = 0;   
			int index = ip.indexOf("/");
			if(index != -1) {
				String[] b =  ip.split("/");
				len = Integer.parseInt(b[1]);
				String str = b[0];
				if(str.indexOf(".") != -1) b = str.split("\\.");
				else b = new String[] {str};
				//同时处理了省略后缀型和标准型
				for(int i = 0; i < b.length; i++)  Ip[i] = Integer.parseInt(b[i]);
				for(int i = b.length; i<4 ;i++)  Ip[i] = 0;
			}else {//省略长度型
				String[] b =  new String[]{ip};
				if(ip.indexOf(".") != -1) b = ip.split("\\.");
				len = b.length * 8;
				for(int i = 0;i < b.length;i++)  Ip[i] = Integer.parseInt(b[i]);
				for(int i = b.length; i < 4; i++)  Ip[i] = 0;
			}
			prefix prefix = new prefix(Ip,len);
			list.add(prefix);
		}
		
		Collections.sort(list);
		
		List<prefix> list1 = new ArrayList<prefix>();
		
		//从小到大合并 从list找到合并后的元素放到list1里面
		int size = list.size() - 1;
		int min;
		int[] ip1, ip2;
		
		//k和k + 1匹配,能匹配则删掉k + 1,继续和新的k + 1匹配
		int k = 0, nxt;//nxt指向第一个不能和k合并的值
		while(k <= size) {
			list1.add(list.get(k));
			nxt = k + 1;
			if(nxt > size) break;
			while(nxt <= size) {
				min = Math.min(list.get(k).len, list.get(nxt).len);
				ip1 = and(list.get(k).ip,min);
				ip2 = and(list.get(nxt).ip,min);
				//取更小的长度min min之后的部分截掉变成0, 如果计算结果相同说明它们的匹配集相同
				if(cmp(ip1, ip2) == 0) 
					nxt++;
				else break;				
			}
			k = nxt;
		}
		
		
		list.clear();
		size = list1.size() - 1;
		for(int i = 0; i <= size; i++){
			list.add(list1.get(i));
		}
 
		//同级合并,永远从栈顶开始找
		Stack<prefix> list2 = new Stack<prefix>();
		size = list.size();
		int compare = 1;
		list2.push(list.get(0));
		while(compare < size) {
			prefix from = list2.pop();
			prefix get = can_combine2(from, list.get(compare));
			if(get == from) {
				list2.push(from);
				list2.push(list.get(compare));
				compare++;
			}
			else {
				list.set(compare, get);
				if(list2.empty()) {
					list2.push(list.get(compare));
					compare++;
				}
			}
		}
		
		size = list2.size();
		for(int i = 0; i < size; i++) list1.set(i, list2.pop());
		list.clear();
		for(int i = size - 1; i >= 0; i--) list.add(list1.get(i));
		
//		in.close();
			
		StringBuilder sb = new StringBuilder();
		for(prefix show:list) {
			sb.append(show.ip[0]+"."+show.ip[1]+
					"."+show.ip[2]+"."+show.ip[3]+"/"+show.len + "\n");
			
		}
		sb.append(" ");
		System.out.print(sb);
//		for(prefix show:list) {
//			System.out.println(show.ip[0]+"."+show.ip[1]+
//					"."+show.ip[2]+"."+show.ip[3]+"/"+show.len);
//		}
		
		
	}
	
	public static prefix can_combine2(prefix a, prefix b) {
		//如果不能合并,返回a
		if(a.len != b.len) return a;
		int len = a.len - 1;
		int[] ip1 = and(a.ip, len);
		int[] ip2 = and(b.ip, len);
		if(cmp(ip1, ip2) == 0) return new prefix(ip1, len);
		else return a;
	}
	
	public static int cmp(int[] x, int[] y) {
		for(int i = 0; i < 4; i++) {
			if(x[i] > y[i])
				return 1;
			if(x[i] < y[i])
				return -1;
		}
		return 0;
	}
	
	public static int cmp1(prefix a, prefix b) {
		//判断a是否比b大, a > b返回1, a < b返回-1,a == b返回0
		int[] x = a.ip;
		int[] y = b.ip;
		for(int i = 0;i < 4;i++) {
			if(x[i] > y[i])
				return 1;
			else if(x[i] < y[i])
				return -1;
		}
		if(a.len < b.len) return -1;
		else if(a.len == b.len) return 0;
		else return 1;
	}
	
	//获得一个前len位和p一样,后面为0的ip地址,用长度为4的数组表示
	public static int[] and(int[] p, int len) {
		int n = len / 8;
		int m = len % 8;
		int[] P = new int[4];
		for(int i = 0; i < n; i++) P[i] = p[i];
		//-1的二进制位全部是1,左移8-m位刚好使末尾8-m位是0
		if(n<4) P[n] = p[n] & (-1 << (8 - m));
		for(int i = n + 1; i < 4; i++) {
			P[i] = 0;
		}
		return P;
	}
}

4.数据中心

试题编号: 4
试题名称: 数据中心
时间限制: 1.0s
内存限制: 512.0MB
在这里插入图片描述
在这里插入图片描述
样例输入
4
5
1
1 2 3
1 3 4
1 4 5
2 3 8
3 4 2
样例输出
4
样例说明
  下图是样例说明。
在这里插入图片描述
在这里插入图片描述
注意:子任务4中,n 改为5*104

c++代码(100分)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>

using namespace std;
int n, m, i, j, u, v, total;
int res = 0;

class Edge{
public:
    int start,end;
    int len;
};

Edge edge[500000];
int pre[100000];
long int ans=0;

int max(int a,int b)
{
	if(a>b)
		return a;
	return b;
}
 
int find(int x){
    if(pre[x] == x){
        return x;
    }
	
	else
	{
        pre[x]=find(pre[x]);
        return pre[x];
    }   
}
 
bool cmp(Edge a, Edge b){
    return a.len < b.len;
}
 
inline void kruskal(){
    for(int i = 1; i <= m; i++){
        u=find(edge[i].start);
        v=find(edge[i].end);
		cout<<u<<" "<<v<<endl;

        if(u == v) continue;

        ans += edge[i].len;
        res = max(res, edge[i].len);
        pre[u] = v;
        total++;
        if(total == n - 1) break;
    }
}
 
int main(){
    cin >> n >> m;//n是点的个数,m是边数
    int root;
    cin >> root;
    for(i = 1; i <= n; i++)//顶点集合
		pre[i] = i;
    for(i = 1; i <= m; i++){//边集合
        cin >> edge[i].start >> edge[i].end >> edge[i].len;
    }
    sort(edge+1,edge+m+1,cmp);//按照len值从小到大对edge排序
    kruskal();
    
    cout << res << endl;
    return 0;
}

java代码(20分)

先写的c++,然后根据c++改的代码,不知道为啥只有二十分了

package csp15;
import java.util.Scanner;
class Edge {
	public int start;
	public int end;
    public int len;
    public Edge(){}
    public Edge(int a,int b,int c){
    	start=a;
    	end=b;
    	len=c;
    }
}
public class Main {
	
	public static int max(int a,int b){
		if(a>b)
			return a;
		else return b;
	}
	public static int find(int[] pre,int x){
		if(pre[x] == x){
	        return x;
	    }else{
	        pre[x]=find(pre,pre[x]);
	        return pre[x];
	    }   
	}
	public boolean cmp(Edge a, Edge b){
	    return a.len < b.len;
	}
	public static int kruskal(Edge[] edge,int[] pre,int m,int n,int res,int total,long ans){
		int u,v;
	    for(int i = 1; i <= m; i++){
	        u=find(pre,edge[i].start);
	        v=find(pre,edge[i].end);
	        
	        if(u == v) continue;

	        ans += edge[i].len;
	        res = max(res, edge[i].len);
	        pre[u] = v;
	        total++;
	        if(total == n - 1) break;
	    }
	    return res;
	}
	public static Edge[] sort(Edge[]edge,int m){
		int a,b,c;
		int j=0;
		for(int i=1;i<=m-1;i++){
			for(j=1;j<=m-i;j++){
			if(edge[j].len>edge[j+1].len){
				a=edge[j].start;
				b=edge[j].end;
				c=edge[j].len;
				edge[j].start=edge[j+1].start;
				edge[j].end=edge[j+1].end;
				edge[j].len=edge[j+1].len;
				edge[j+1].start=a;
				edge[j+1].end=b;
				edge[j+1].len=c;
			}
			}
		}
		return edge;
	}

	public static void main(String[] args) {
		int n,m,i;
		int res = 0;
		int total=0;
		long ans=0;
		Edge edge[]=new Edge[500000];
		Edge edge2[]=new Edge[500000];
		int pre[]=new int[100000];
		Scanner input=new Scanner(System.in);
		n=input.nextInt();
		m=input.nextInt();
		//n是点的个数,m是边数
	    
		int root;
	    root=input.nextInt();
	    //System.out.println(n+" "+m+" "+root);
	    for(i = 1; i <= n; i++)//顶点集合
			pre[i] = i;
	    
	    
	    for(i = 1; i <= m; i++){
	    	edge[i]=new Edge();
	    }
	    for(i = 1; i <= m; i++){//边集合
	    	edge[i].start=input.nextInt();
	    	edge[i].end=input.nextInt();
	    	edge[i].len=input.nextInt();
	    	//System.out.println(edge[i].start+" "+edge[i].end+" "+edge[i].len);
	    }
	    edge2=sort(edge,m);//按照len值从小到大对edge排序
	    /*
	    for(i = 1; i <= m; i++){//边集合
	    	System.out.println(edge2[i].start+" "+edge2[i].end+" "+edge2[i].len);
	    }*/
	    res=kruskal(edge2,pre,m,n,res,total,ans);
	    System.out.println(res);
	    input.close();
	}
}
/*
4
5
1
1 2 3
1 3 4
1 4 5
2 3 8
3 4 2
*/

java代码(100分)

这个是转载的,不知道为啥他这个样例竟然没过,但却是100分

package csp15;
import java.awt.SystemColor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
public class Main {
		
		public static void main(String[] args) {
			// TODO Auto-generated method stub
			Scanner in = new Scanner(System.in);
			List<int[]> allp = new ArrayList<>();  //接收m条边和其权值的列表
			int ans = -1;      	//所需要的答案 
			
			int n = in.nextInt();
			int m = in.nextInt();
			int root= in.nextInt();
			int[] nn = new int[n];     //n个点 
			
			for(int i=0;i<m;i++)
			{
				int[] mn= new int[3];
				mn[0]=in.nextInt();
				mn[1]=in.nextInt();
				mn[2]=in.nextInt();
				allp.add(mn);
			}
			Collections.sort(allp, new Comparator<int[]>() {     //按权值排序
				@Override
				public int compare(int[] a,int[] b)
				{
					if(a[2]>b[2])
						return 1;
					else
						return -1;
				}
			});
			for(int i=0;i<allp.size();i++)
			{
				if(nn[allp.get(i)[1]-1]!=1||nn[allp.get(i)[0]-1]!=1)     //判断此边的两个点是否已被连接
				{
					nn[allp.get(i)[1]-1]=1;
					nn[allp.get(i)[0]-1]=1;
					if(allp.get(i)[2]>ans)  //更新最小树的最大权值
						ans=allp.get(i)[2];
				}
			}
			System.out.println(ans);  //输出答案
		}
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值