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

问题 A: 菱形图案
[命题人 : admin]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 1029提交量: 2680统计

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

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

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

样例输入 Copy
2
3
4
样例输出 Copy
  * 
 * * 
* * * 
 * * 
  * 

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

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


#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    while(cin >> n){
        for(int i = 1;i <= n + 1;i++){
            for(int j = 1;j <= n - i + 1;j++){
                cout << " ";
            }
            for(int j = 1;j <= i;j++){
                cout << "* ";
            }
            cout << endl;
        }
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= i;j++){
                cout << " ";
            }
            for(int j = 1;j <= n - i + 1;j++){
                cout << "* ";
            }
            cout << endl;
        }
        cout << endl;
    }
    return 0;

问题 B: X星人的礼物
[命题人 : admin]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 324提交量: 1196统计

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

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

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

样例输入 Copy
5 80
20 70 40 30 10
样例输出 Copy
3
这个就是用双指针

#include<bits/stdc++.h>
using namespace std;
bool vis[100010];
int main(){
    int n,c;
    while(cin >> n >> c){
        vector<int>a;
        for(int i = 1;i <= n;i++){
            int x;
            cin >> x;
            a.push_back(x);
        }
        int ans = 0;
        sort(a.begin(),a.end());
        int r = n - 1,l = 0;
        while(l < r){
            if(a[l] + a[r] <= c){
                ans++;
                l++;
                r--;
            }else{
                ans++;
                r--;
            }
        }
        if(l != r){
            cout << ans << endl;
        }else{
            if(a[l] <= c)cout << ans + 1 << endl;
            else cout << ans << endl;
        }
    }
    return 0;
}

问题 C: 隔离14天
[命题人 : 201501010119]
时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表
解决: 1373提交量: 2397统计
题目描述
      现在假定编号为0的乘客冠状病毒核酸检验呈阳性,请编写一个程序统计需隔离的总人数(包括编号为0的乘客)。

输入
第1行的第1个数字n表示总人数,第2个数字m表示汽车数量;从第2行开始,接下来的m行表示每辆汽车的司乘人员总人数和人员编号(人员编号是一个固定值,可以对应于我们的身份证号码),每一行的第1个数字k表示该汽车的司乘人员总数,接下来的k个数字表示每一个人的编号。
输出
需要被隔离的总人数。
样例输入 Copy
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 a[10010],b[10010];
int main(){
    int n,m;
    while(cin >> n >> m){
        int ans = 1;
        for(int i = 0;i < m;i++){
            cin >> b[i];
            int c[b[i]];
            for(int j = 0;j < b[i];j++){
                cin >> c[j];
            }
            for(int j = 0;j < b[i];j++){
                if(a[c[j]] == 0){
                    a[c[j]] = ans;
                }else {
                    for(int k = 0;k < b[i];k++){
                        a[c[k]] = a[c[j]];
                    }
                }
            }
            ans++;
        }
        ans = 0;
        for(int i = 0;i < n;i++){
            if(a[i] == a[0]){
                ans++;
            }
        }
        cout << ans << endl;
    }
    return 0;
}

问题 D: 最小生成树(Kruskal)
[命题人 : 201501010119]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 987提交量: 1922统计

题目描述
编程实现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;
const int N = 10100;
struct node{
    int a,b;
    int w;
}arr[N];
int f[N];
int find(int x){
    if(f[x] != x){
        f[x] = find(f[x]);
    }
    return f[x];
}
void mer(int x1,int y1){
    f[find(y1)] = find(x1);
}
bool cmp(node x,node y){
    return x.w < y.w;
}
int main(){
    int n,m;
    while(cin >> n >> m){
        int ans = 0;
        int k = 0;
        for(int i = 1;i <= m;i++){
            cin >> arr[i].a >> arr[i].b >> arr[i].w;
        }
        for(int i = 1;i <= n;i++)f[i] = i;
        sort(arr + 1,arr + 1 + m,cmp);
        for(int i = 1;i <= m;i++){
            if(find(arr[i].a) != find(arr[i].b)){
                mer(arr[i].a,arr[i].b);
                ans += arr[i].w;
                k++;
            }
            if(k == n - 1){
                cout << ans << endl;
                break;
            }
        }
    }
    return 0;
}

问题 E: 搭建电路
[命题人 : admin]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 770提交量: 3016统计

题目描述
明明迷上了一个搭建电路的游戏。
在游戏中,每次在两个电子元件之间增加一条有效电路(两个元件之间先前没有电路相连)都将获得相应的积分奖励。
已知电子元件数量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
这个就是最大生成树,注意num(num<1e9)所以要longlong

#include<bits/stdc++.h>
using namespace std;
const int N = 10100;
using ll = long long;
struct node{
    ll a,b;
    ll w;
}arr[N];
int f[N];
ll find(int x){
    if(f[x] != x){
        f[x] = find(f[x]);
    }
    return f[x];
}
bool mer(int x,int y){
    int ans = find(x);
    int res = find(y);
    if(ans != res){
        f[res] = ans;
        return true;
    }else return false;
}
bool cmp(node x,node y){
    return x.w > y.w;
}
int main(){
    int n,m;
    while(cin >> n >> m){
        ll ans = 0;
        ll k = 0;
        bool flag = false;
        for(int i = 1;i <= m;i++){
            cin >> arr[i].a >> arr[i].b >> arr[i].w;
        }
        for(int i = 1;i <= n;i++)f[i] = i;
        sort(arr + 1,arr + 1 + m,cmp);
        for(int i = 1;i <= m;i++){
            if(mer(arr[i].a,arr[i].b)){
                ans += arr[i].w;
            }
        }
        int sum = 0;
        for(int i = 1;i <= n;i++){
            if(f[i] == i){
                sum++;
                if(sum >= 2){
                    cout << "No solution." << endl;
                    return 0;
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}

问题 F: 最小生成树(Prim)
[命题人 : 201501010119]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 1010提交量: 4987统计

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

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

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

样例输入 Copy
3 3
0 1 10
0 2 15
1 2 50
样例输出 Copy
0 1 10
0 2 15
#include<bits/stdc++.h>
using namespace std;
const int N = 5000;
const int INF = 0x3f3f3f3f;
using ll = long long;
int a[N][N];
bool vis[N];
int n,m;
struct er{
    int x,y,z;
};
er res[N];
bool cmp(er q,er w){
    if(q.x != w.x)
        return q.x <= w.x;
    else return q.y <= w.y;
}
int flag = 0;
void prim(){
    vis[0] = true;
    int arr[N],sum[N];
    for(int i = 0;i < n;i++){
        arr[i] = fabs(a[0][i]);
        sum[i] = 0;
    }
    for(int i = 1;i < n;i++){
        int j = 0;
        for(int k = 0;k < n;k++){
            if(!vis[k] && arr[k] < arr[j]){
                j = k;
            }
        }
        if(a[sum[j]][j] > 0){
            res[flag].x = sum[j];
            res[flag].y = j;
            res[flag].z = arr[j];
            flag++;
        }
        else {
            res[flag].x = j;
            res[flag].y = sum[j];
            res[flag].z = arr[j];
            flag++;
        }
        vis[j] = true;
        for(int i = 0;i < n;i++){
            if(!vis[i] && (a[j][i] < arr[i])){
                arr[i] = fabs(a[j][i]);
                sum[i] = j;
            }
        }
    }
}
int main(){
    while(cin >> n >> m){
        flag = 0;
        int x,y,z;
        memset(a,INF,sizeof(a));
        memset(vis,false,sizeof vis);
        for(int i = 0;i < m;i++){
            cin >> x >> y >> z;
            a[x][y] = z;
            a[y][x] = -1 * z;
        }
        prim();
        sort(res,res + flag,cmp);
        for(int i = 0;i < flag ;i++){
            cout << res[i].x << " " << res[i].y << " " << res[i].z << endl;
        }
    }
    return 0;
}

问题 G: 台球碰撞
[命题人 : 外部导入]
时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表
解决: 28提交量: 87统计
题目描述
在平面直角坐标系下,台球桌是一个左下角在(0,0),右上角在(L,W)的矩形。有一个球心在(x,y),半径为R的圆形母球放在台球桌上(整个球都在台球桌内)。受撞击后,球沿极角为a的射线(即:x正半轴逆时针旋转到此射线的角度为a)飞出,每次碰到球桌时均发生完全弹性碰撞(球的速率不变,反射角等于入射角)。

如果球的速率为v,s个时间单位之后球心在什么地方?

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

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

样例输入 Copy
100 100 80 10 5 90 2 23
110 100 70 10 5 180 1 9999
0 0 0 0 0 0 0 0
样例输出 Copy
80.00 56.00
71.00 10.00
这个就是一个几何的水题,不用想的太复杂了

#include<bits/stdc++.h>
using namespace std;
int main(){
    int l,w,r,a,v,s;
    int t;
    double vx,vy,x,y;
    double pi = acos(-1.0);
    while( cin>>l>>w>>x>>y>>r>>a>>v>>s )
    {
        if( l==0 ) break;
        vy=sin( a*pi/180 )*v;
        vx=cos( a*pi/180 )*v;
        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++;
        }
        cout << fixed << setprecision(2) << x << " " << y << endl;
    }
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值