《算法分析与设计》练习13

我的代码尽量做到通俗易懂,难理解的代码都会有解释,跟着思路来,总会有收获

1的个数

题目描述
输入一个int型的正整数,计算出该int型数据在内存中存储时1的个数。
输入
输入一个整数(int类型)。
输出
这个数转换成2进制后,输出1的个数。
样例输入 Copy
5
样例输出 Copy
2

#include<vector>
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;

int main(){
	int n;
	cin>>n;
	int a[1005]={0};
	int k=0,cnt=0;
	while(1){
		if(n<2)break;
		a[k]=n%2;
		n=n/2;
		k++;
	}
	a[k]=n;
	for(int i=0;i<=k;i++){
		if(a[i]==1)cnt++;
	}
	cout<<cnt<<endl; 
	return 0;
} 

最小素数对

任意一个偶数(大于2)都可以由2个素数组成,组成偶数的2个素数有很多种情况,本题目要求输出组成指定偶数的两个素数差值最小的素数对。

输入
输入一个偶数。
输出
输出两个素数。
样例输入 Copy
20
样例输出 Copy
7
13

#include<vector>
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int a[10005];
 bool prime(int k){
 	for(int i=2;i<=sqrt(k);i++){
 		if(k%i==0){
 			return false;			
		 }
	 }
	 return true;//因为如果不是素数已经放回了false,不会执行到这里 
 }
int main(){
	//思路因为是偶数且需要最小差值,那么直接从中间开始找
	 int n;
	 cin>>n;	 	 
	 int num=n/2,k=0,cnt=0;
	 	for(int i = 0;i < num;i++){//同加同减加一起还是n 
            if(prime(num - i) && prime(num + i)){
                cout << num - i << endl; 
                cout << num + i << endl;
                break;
            }
        }       
	
	 
	return 0;
} 

工作单位

题目描述
在某个城市中住着n个人,现在给定关于这n个人的m条信息(即某2个人认识)。
假设所有认识的人一定属于同一个单位,请计算该城市有多少个单位?
输入
第1行的第1个值表示总人数n,第2个值表示总信息数m;第2行开始为具体的认识关系信息
输出
单位的个数
样例输入 Copy
10 4
2 3
4 5
4 8
5 8
样例输出 Copy
7
代码解释点这里

14天

题目描述

第1行的第1个数字n表示总人数,第2个数字m表示汽车数量;从第2行开始,接下来的m行表示每辆汽车的司乘人员总人数和人员编号(人员编号是一个固定值,可以对应于我们的身份证号码),每一行的第1个数字k表示该汽车的司乘人员总数,接下来的k个数字表示每一个人的编号。
输出
总人数。
样例输入 Copy
100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
样例输出 Copy
4

#include<bits/stdc++.h>
using namespace std;

int f[1005];
int rk[1005];

int find(int t){
    
	if(t!=f[t])f[t]= find(f[t]);   
	 return f[t];
}

void merge(int a,int b){
	int x=find(a);
	int y=find(b);
	if(x!=y){
	if(rk[x]>rk[y])
		f[y]=x;
		else{
			f[x]=y;
			if(rk[x]==rk[y])rk[y]++;
		}
		
	}
	 
}
int main(){

	int n,m;
	cin>>n>>m;

	for(int i=0;i<n;i++){
		f[i]=i;
		rk[i]=0;
	}
	
	for(int i=0;i<m;i++){
		int k,a;
		cin>>k;//每一行的个数
		cin>>a; //每一行的第二个数,也就是一辆车中的第一个位乘客,把他当成是这练车里面的所有人
		//的祖先,也就是根节点		
		int b;//输入后面的几位乘客
		for(int j=1;j<k;j++){
			cin>>b;					
			merge(a,b);	//合并	
		}
	}
	int cnt=0;
	for(int i=0;i<n;i++){
//		cout<<i<<" "<<f[i]<<endl;
		if(f[i]==f[0])cnt++;//如果一个人的根节点和0好的更结点一样那就是需要ge li的人
	}
	cout<<cnt<<endl;

	return 0;
}

最小生成树

题目描述
编程实现Kruskal算法,求图的最小生成树(MST)的权重。
输入
每组数据分为两个部分,第一部分为图的点数n,和边数m,
第二部分为m行,每一行输入三个数字,前两个为两个顶点的编号,第三个为边权重。
输出
最小生成树的权重。
样例输入 Copy
3 3
0 1 10
0 2 15
1 2 50
样例输出 Copy
25

#include<bits/stdc++.h>
using namespace std;

struct node{
	int p1,p2;//两个点 
	int c;//成本 
}e[1005];
node E[1005];
bool cmp(node x,node y){
	return x.c<y.c;
}

int pre[1005],sum=0;

int find(int t){
	if(pre[t]==t)return t;
	else return find(pre[t]); 
}
bool merge(int x,int y){//判断图是否连通
	int a=find(x);
	int b=find(y);
	if(a!=b){
	pre[b]=a;
	return true;
	}
	else return false;
}
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++){  //输入m条边 
		cin>>e[i].p1>>e[i].p2>>e[i].c; 
	}
	for(int i=0;i<n;i++)pre[i]=i;//初始化前驱结点 
	sort(e,e+m,cmp);
	int k=0;
	for(int i=0;i<m;i++){
		 if(merge(e[i].p1,e[i].p2)){//如果为true则表明p1点和p2点还没有连上
		 	sum+=e[i].c;
		 }		
		}
	cout<<sum<<endl;
	return 0;
}

搭建电路

题目描述
明明迷上了一个搭建电路的游戏。
在游戏中,每次在两个电子元件之间增加一条有效电路(两个元件之间先前没有电路相连)都将获得相应的积分奖励。
已知电子元件数量n和部分电子元件之间的奖励积分值。如何构建一个有效电路将所有元件全部连接起来,并且可以得到最多的积分奖励。
输入
每组输入数据包含m+1行。
第1行输入两个正整数n和m,其中n表示电子元件数量(n<=100),m表示提供了m对电子元件之间的奖励积分值(m<=1000)。两个正整数之间用空格隔开。
第2行到第m+1行对应m对电子元件及其对应的奖励积分值,每一行包含三个正整数,第1个和第2个整数表示电子元件编号(从1开始),第3个整数表示两个元件之间搭建电路的奖励积分num(num<1e9)。整数之间用空格隔开。
输出
每组输出占1行,输出一个正整数,即最多可以得到的积分奖励值。如果没有办法把所有元件全部连接起来,则输出“No solution.”。
样例输入 Copy
3 3
1 2 10
1 3 20
2 3 30
样例输出 Copy
50

#include<bits/stdc++.h>

using namespace std;

struct node{
	int p1,p2;//两个点 
	long long c;//成本 
}e[10005];

bool cmp(node x,node y){
	return x.c>y.c;//优先考虑奖励多的
}

int pre[1005];
long long sum=0;

int find(int t){
	if(pre[t]==t)return t;
	else return pre[t]=find(pre[t]); 
}
bool merge(int x,int y){//判断图是否连通
	int a=find(x);
	int b=find(y);
	if(a!=b){
	pre[b]=a;
	return true;
	}
	else return false;
}
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++){  //输入m条边 
		cin>>e[i].p1>>e[i].p2>>e[i].c; 
	}
	for(int i=0;i<=n;i++)pre[i]=i;//初始化前驱结点 
	sort(e,e+m,cmp);
	int k=0;
	for(int i=0;i<m;i++){
		 if(merge(e[i].p1,e[i].p2)){//如果为true则表明p1点和p2点还没有连上,
//则将其加入另外一个结构体,因为题目要求要排序
		 	
			 sum+=e[i].c;//总奖励
		 }			 
		}
		int cnt=0;
		for(int i=1;i<=n;i++){
			if(pre[i]==i){
				cnt++;
				if(cnt>=2){//这里为什么是大于2就表示没有连通呢?因为根节点没有父节点是他本身
				//,所以一旦有另一个点的父节点等于它本身那么这个图就是不连通的
					cout<<"No solution."<<endl;
					return 0;
				}
			
			}
			//cout<<pre[i]<<" ";
		}
		
	printf("%lld\n",sum);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

H-rosy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值