2024年春季学期《算法分析与设计》练习13

A:菱形图案

KiKi学习了循环,BoBo老师给他出了一系列打印图案的练习,该任务是打印用“*”组成的菱形图案。

输入

多组输入,一个整数(2~20)。

输出

针对每行输入,输出用“*”组成的菱形,每个“*”后面有一个空格。每输出一个菱形的后面需要空一行。 

样例输入

2

3

4

样例输出

  * 
 * * 
* * * 
 * * 
  * 

   * 
  * * 
 * * * 
* * * * 
 * * * 
  * * 
   * 

    * 
   * * 
  * * * 
 * * * * 
* * * * * 
 * * * * 
  * * * 
   * * 
    *

#include<iostream>
using namespace std;
typedef long long ll; 
const int N=5e2+5,M=1e5+5,INF=0x3f3f3f3f;
int n; 
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    while(cin>>n){
    	for(int i=n;i>=0;i--){
    		for(int j=0;j<i;j++) cout<<' ';
    		for(int j=i;j<=n;j++) cout<<"* ";
			cout<<'\n'; 
		}
		for(int i=1;i<=n;i++){
    		for(int j=0;j<i;j++) cout<<' ';
    		for(int j=i;j<=n;j++) cout<<"* ";
			cout<<'\n'; 
		}
		cout<<'\n';
	}
    return 0;
}

B:X星人的礼物 

六一儿童节到了,X星人宝宝收到了很多很多礼物。他决定把这些礼物装到自己的礼物箱中。为此,他准备了很多个型号相同的礼物箱,每个礼物箱能够装礼物的最大重量都是一样的。但是X星人宝宝不希望在一个礼物箱里面装太多礼物(可能担心礼物会被压坏吧),每个礼物箱最多只允许装2个礼物
假设X星人宝宝收到了N个礼物,现在给出每一个礼物的重量和一个礼物箱的最大装载量,请你编写一个程序计算X星人宝宝最少要用多少个礼物箱才能够把所有的礼物都装完

输入

单组输入。
每组两行,第1行输入两个正整数,分别表示礼物的数量N和每个礼物箱的最大装载量C,其中1<=N<=1000,1<=C<=100,两者之间用英文空格隔开。
第2行输入N个不超过100的正整数,分别表示每一个礼物的重量,两两之间用英文空格隔开。
输入保证最重的礼物的重量<=C。

输出

针对所输出的数据,输出将所有的礼物全部都装完所需的礼物箱的最少个数。 

样例输入

5 80

20 70 40 30 10 

样例输出

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=1e3+5,M=1e5+5,INF=0x3f3f3f3f;
int n,m,s; 
int a[N];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>a[i];
    sort(a,a+n);
    for(int i=0,j=n-1;i<n;){
    	if(i==j){
    		s++;
    		break;
		}
		if(i>j) break;
		if(a[i]+a[j]<=m) {
			i++;
			j--;
		}else j--;
		s++;
	}
	cout<<s<<'\n';
    return 0;
}

 C:隔离14天

如果实施更为严格的防控措施,一辆汽车上有一个确诊患者或者密切接触者,那么该汽车上所有的人都被认为是密切接触者,全部需要自行居家隔离或者集中隔离14天。
      现在假定编号为0的乘客冠状病毒核酸检验呈阳性,请编写一个程序统计需隔离的总人数(包括编号为0的乘客)。

输入

第1行的第1个数字n表示总人数,第2个数字m表示汽车数量;从第2行开始,接下来的m行表示每辆汽车的司乘人员总人数和人员编号(人员编号是一个固定值,可以对应于我们的身份证号码),每一行的第1个数字k表示该汽车的司乘人员总数,接下来的k个数字表示每一个人的编号。

输出

需要被隔离的总人数。 

样例输入

100 4

2 1 2

5 10 13 11 12 14

2 0 1

2 99 2 

 样例输出

4

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=1e3+5,M=1e5+5,INF=0x3f3f3f3f;
int n,m,k,x,y,fa,fb;
int f[N],cnt[N];
int find(int x)
{
	if(x!=f[x]) f[x]=find(f[x]);
	return f[x];
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n>>m;
    for(int i=0;i<n;i++) {
		f[i]=i;
		cnt[i]=1;
	}
    while(m--){
    	cin>>k>>y;
    	while(--k){
    		cin>>x;
    		fa=find(x),fb=find(y);
    		if(fa!=fb){
    			f[fa]=fb;
    			cnt[fb]+=cnt[fa];
			}
		}
	}
	cout<<cnt[find(0)]<<'\n';
    return 0;
}

 D:最小生成树(Kruskal)

编程实现Kruskal算法,求图的最小生成树(MST)的权重。

输入

每组数据分为两个部分,第一部分为图的点数n,和边数m, 
第二部分为m行,每一行输入三个数字,前两个为两个顶点的编号,第三个为边权重。 

输出

最小生成树的权重。 

样例输入

3 3

0 1 10

0 2 15

1 2 50 

样例输出

25 

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=1e3+5,M=1e5+5,INF=0x3f3f3f3f;
int n,m,cnt,res;
int a,b,c;
int fa,fb;
int f[N];
struct edge
{
	int a,b,c;
	bool operator<(const edge& W)const{
		return c<W.c;
	}
}edges[M];
int find(int x)
{
	if(x!=f[x]) f[x]=find(f[x]);
	return f[x];
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n>>m;
    for(int i=0;i<n;i++) f[i]=i;
    for(int i=0;i<m;i++){
    	cin>>a>>b>>c;
		edges[i]={a,b,c}; 
	}
	sort(edges,edges+m);
	for(int i=0;i<m;i++){
		a=edges[i].a,b=edges[i].b,c=edges[i].c;
		fa=find(a),fb=find(b);
		if(fa!=fb){
			f[fb]=fa;
			res+=c;
			cnt++;
		}
		if(cnt==n-1) break;
	}
	cout<<res<<'\n';
    return 0;
}

 E:搭建电路

明明迷上了一个搭建电路的游戏。
在游戏中,每次在两个电子元件之间增加一条有效电路(两个元件之间先前没有电路相连)都将获得相应的积分奖励。
已知电子元件数量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.”。 

样例输入

3 3

1 2 10

1 3 20

2 3 30

样例输出

50 

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=1e3+5,M=1e5+5,INF=0x3f3f3f3f;
int n,m,cnt;
ll res;
int a,b,c;
int fa,fb;
int f[N];
struct edge
{
	int a,b,c;
	bool operator<(const edge& W)const{
		return c>W.c;
	}
}edges[M];
int find(int x)
{
	if(x!=f[x]) f[x]=find(f[x]);
	return f[x];
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n>>m;
    for(int i=0;i<n;i++) f[i]=i;
    for(int i=0;i<m;i++){
    	cin>>a>>b>>c;
		edges[i]={a,b,c}; 
	}
	sort(edges,edges+m);
	for(int i=0;i<m;i++){
		a=edges[i].a,b=edges[i].b,c=edges[i].c;
		fa=find(a),fb=find(b);
		if(fa!=fb){
			f[fb]=fa;
			res+=c;
			cnt++;
		}
		if(cnt==n-1) break;
	}
	if(cnt==n-1) cout<<res<<'\n';
	else cout<<"No solution.\n";
    return 0;
}

 F:最小生成树(Prim)

使用Prim算法求图的最小生成树(MST)

输入

每组数据分为两个部分,第一部分为图的点数n,和边数m,
第二部分为m行,每一行输入三个数字,前两个为两个顶点的编号,第三个为边权重。

输出

最小生成树,输出时按照边的两个端点的升序输出。(先看左端点,再看右端点,端点不换位置) 

样例输入

3 3

0 1 10

0 2 15

1 2 50 

样例输出

0 1 10

0 2 15 

易错提示:注意输入的左端点、右端点

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=5e2+5,M=1e5+5,INF=0x3f3f3f3f;
int n,m,res;    
int a,b,c;
int g[N][N],backup[N],dist[N];
bool st[N],stt[N][N];
struct edge
{
    int a,b,c;
    bool operator<(const edge& W)const{
        if(a==W.a) return b<W.b;
        return a<W.a;
    }
}edges[M];
void prim()
{
    res=0;
    for(int i=0;i<n;i++){
        int t=-1;
        for(int j=0;j<n;j++) if(!st[j]&&(t==-1||dist[t]>dist[j])) t=j;
        st[t]=true;
        if(i) edges[res++]={backup[t],t,dist[t]};
        for(int j=0;j<n;j++) if(!st[j]&&dist[j]>g[t][j]) {
            dist[j]=g[t][j];
            backup[j]=t;
        }
    }
    sort(edges,edges+res);
    for(int i=0;i<res;i++) {
        a=edges[i].a,b=edges[i].b,c=edges[i].c;
        if(stt[a][b]) cout<<a<<' '<<b<<' '<<c<<'\n';
        else cout<<b<<' '<<a<<' '<<c<<'\n';
    }  
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    while(cin>>n>>m){
        memset(g,0x3f,sizeof g);
        memset(dist,0x3f,sizeof dist);
        memset(st,false,sizeof st);
        while(m--){
            cin>>a>>b>>c;
            stt[a][b]=true;
            g[a][b]=g[b][a]=min(g[a][b],c); 
        }
        prim();
    }
    return 0;
}

G:台球碰撞

在平面直角坐标系下,台球桌是一个左下角在(0,0),右上角在(L,W)的矩形。有一个球心在(x,y),半径为R的圆形母球放在台球桌上(整个球都在台球桌内)。受撞击后,球沿极角为a的射线(即:x正半轴逆时针旋转到此射线的角度为a)飞出,每次碰到球桌时均发生完全弹性碰撞(球的速率不变,反射角等于入射角)。如果球的速率为vs个时间单位之后球心在什么地方?

输入

输入文件最多包含25组测试数据,每个数据仅一行,包含8个正整数L,W,x,y,R,a,v,s(100<=L,W<=105,1<=R<=5, R<=x<=L-RR<=y<=W-R, 0<=a<360, 1<=v,s<=105),含义见题目描述。L=W=x=y=R=a=v=s=0表示输入结束,你的程序不应当处理这一行。

输出

对于每组数据,输出仅一行,包含两个实数xy,表明球心坐标为(x,y)。xy应四舍五入保留两位小数。 

样例输入

100 100 80 10 5 90 2 23

110 100 70 10 5 180 1 9999

0 0 0 0 0 0 0 0

样例输出

80.00 56.00

71.00 10.00 

易错提示 :pi

#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll; 
const int N=5e2+5,M=1e5+5,INF=0x3f3f3f3f;
double L,W,x,y,R,a,v;
int s,t; 
double vx,vy;
double pi=acos(-1.0);
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    while(cin>>L>>W>>x>>y>>R>>a>>v>>s&&L+W+x+y+R+a+v+s){
    	vy=v*sin(a*pi/180),vx=v*cos(a*pi/180);
		t=0;
		while(t!=s){
			x+=vx;
			y+=vy;
			while(x-R<0||x+R>L||y-R<0||y+R>W){
				if(x-R<0) x=2*R-x,vx=-vx;
				if(x+R>L) x=2*L-2*R-x,vx=-vx;
				if(y-R<0) y=2*R-y,vy=-vy;
				if(y+R>W) y=2*W-2*R-y,vy=-vy;
            }
			t++;
		}
		printf("%.2lf %.2lf\n",x,y);
	}
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值