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

目录

问题 A: 1的个数

 问题 B: 又一道简单题

问题 C: 安置路灯 

问题 D: 单源最短路径问题

问题 E: ABC + DEF = GHI

问题 F: 油田问题


问题 A: 1的个数

题目描述

输入一个int型的正整数,计算出该int型数据在内存中存储时1的个数。

输入

 输入一个整数(int类型)。

输出

这个数转换成2进制后,输出1的个数。

样例输入 Copy
5
样例输出 Copy
2
#include<stdio.h>
int main(){
    int a;
    int count;
 
    while(scanf("%d",&a)!=EOF){
    count=0;
    for(;a>0;)
    {
        if(a%2==1)
        {
            count++;
        }
        a=a/2;
    }
    printf("%d\n",count);
    }
return 0;
}

 问题 B: 又一道简单题

题目描述

输入一个四个数字组成的整数 n,你的任务是数一数有多少种方法,恰好修改一个数字,把它 变成一个完全平方数(不能把首位修改成 0)。比如 n=7844,有两种方法:3844=622 和 7744=882。 

输入

输入第一行为整数 T (1<=T<=1000),即测试数据的组数,以后每行包含一个整数 n (1000<=n<=9999)。 

输出

对于每组数据,输出恰好修改一个数字,把 n变成完全平方数的方案数

样例输入 Copy
2
7844
9121
样例输出 Copy
Case 1: 2
Case 2: 0
#include<stdio.h>
int main(){
    int a;
    int count;
    int sum;
    int js;
    int n;int i;
    int x;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        sum=32;
        count=0;
         
        scanf("%d",&a);
        for(;sum<100;sum++)
        {
            js=0;
            x=sum*sum;
            if((x%10==a%10))
            {
                js++;
            }
            if((x/10%10==a/10%10))
            {
                js++;
            }
            if((x/100%10==a/100%10))
            {
                js++;
            }
            if(x/1000==a/1000)
            {
                js++;
            }
            if(js==3)
            {
                count++;
            }
        }
        printf("Case %d: %d\n",i+1,count);
    }
     
     
     
return 0;
}

问题 C: 安置路灯 

题目描述

小Q正在给一条长度为n的道路设计路灯安置方案。

为了让问题更简单,小Q把道路视为n个方格,需要照亮的地方用'.'表示, 不需要照亮的障碍物格子用'X'表示。

小Q现在要在道路上设置一些路灯, 对于安置在pos位置的路灯, 这盏路灯可以照亮pos - 1, pos, pos + 1这三个位置。

小Q希望能安置尽量少的路灯照亮所有'.'区域, 希望你能帮他计算一下最少需要多少盏路灯。

输入
输入的第一行包含一个正整数t(1 <= t <= 1000), 表示测试用例数
接下来每两行一个测试数据, 第一行一个正整数n(1 <= n <= 1000),表示道路的长度。
第二行一个字符串s表示道路的构造,只包含'.'和'X'。
输出
对于每个测试用例, 输出一个正整数表示最少需要多少盏路灯。
样例输入 Copy
2
3
.X.
11
...XX....XX
样例输出 Copy
1
3
#include<stdio.h>
int main(){
    int a;
    int count;
     
    char c[1002];
    int n;int i;
    int x;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
         
        count=0;
        scanf("%d",&a);
        scanf("%s",c);
        for(x=0;x<a;)
        {
            if(c[x]=='.')
            {
                count++;
            //  if(c[x+1]=='.')
                    x+=3;
                /*  if(c[x+2]=='.')
                    {
                         
                    }
                    else*/
                //else
                    //x++;
                 
            }else
            {
                x++;
            }
        }
        printf("%d\n",count);
    }
return 0;
}

问题 D: 单源最短路径问题

题目描述

编程实现Dijkstra算法,求一个有向加权图中,从源点出发到其他各个顶点的最短路径。

输入

第1行第1个值表示顶点个数,第2个值表示边个数;第2行开始为边(两个顶点,边的起点和终点)及权重。

输出

顶点0到每一个顶点的最短路径长度。

样例输入 Copy
5 7
0 1 10
0 3 30
0 4 100
1 2 50
2 4 10
3 2 20
3 4 60
样例输出 Copy
0 10 50 30 60
import java.util.Scanner;

public class Main {
    private static int[][] map;
    static int[] dis;
    static boolean[] used;
    public static void main(String[] args) {

            Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
            int i = scanner.nextInt();
            int j = scanner.nextInt();
            int x;
            int y;
            Main main = new Main();
            map = new int[i][i];
            dis = new int[i];
            used = new boolean[i];
            for (x = 0; x < i; x++) {
                for (y = 0; y < i; y++) {
                    map[x][y] = Integer.MAX_VALUE;
                }
            }
            map[0][0]=0;
            for (int n = 0; n < j; n++) {
                x = scanner.nextInt();
                y = scanner.nextInt();
                map[x][y] = scanner.nextInt();

            }


            for (int n = 0; n < i; n++) {
                    used[n] = false;
            }
            main.djikstra(i);
            for (int n = 0; n < i; n++) {

                    System.out.print(dis[n] + " ");
            }
            System.out.println();
        }
        scanner.close();
    }
    void djikstra(int n){

        for (int i=0;i<n;i++)//初始化距离数组,dis[i]:第一个点到第i个点的距离
        {
            dis[i] = map[0][i];
        }
        int k=-1;//未访问过且距离最小的点
        for (int i=1;i<n;i++){//控制边数n-1次(条)
            int min = Integer.MAX_VALUE;
            for (int j=0;j<n;j++) {
                if (!used[j] && dis[j] < min) {
                    min = dis[j];
                    k = j;
                }
            }
            if (k == -1) {
                // 如果没有未访问的节点,则提前结束
                break;
            }
            used[k]=true;
            for (int s=0;s<n;s++){
                //!used[j] && map[minIndex][j] != Integer.MAX_VALUE && dis[minIndex] + map[minIndex][j] < dis[j]
                if (!used[s] && map[k][s] != Integer.MAX_VALUE && dis[k] + map[k][s] < dis[s]){
                    // if (!used[s]&&((dis[k]+map[k][s])<dis[s])){
                    dis[s] = dis[k]+map[k][s];
                }
            }
        }

    }
}

问题 E: ABC + DEF = GHI

题目描述

用1, 2, 3...9 这九个数字组成一个数学公式,满足:ABC + DEF = GHI,每个数字只能出现一次,编写程序输出所有的组合。

输入

输出

输出所有的 ABC + DEF = GHI,
每行一条数据,格式为ABC+DEF=GHI
输出结果按照ABC升序排列,如果ABC相同,则按照DEF升序排列。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        findCombinations();
    }

    public static void findCombinations() {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        List<String> combinations = new ArrayList<>();

        permute(numbers, 0, new StringBuilder(), combinations);

        // 排序
        Collections.sort(combinations);

        // 打印结果
        for (String combination : combinations) {
            System.out.println(combination);
        }
    }

    private static void permute(List<Integer> numbers, int level, StringBuilder current, List<String> combinations) {
        if (level == numbers.size()) {
            // 检查是否满足条件
            String str = current.toString();
            if (str.charAt(0) != '0' && // 确保ABC不以0开头
                    str.substring(0, 3).equals(String.valueOf(Integer.parseInt(str.substring(0, 3)))) && // 确保ABC是有效的数字
                    str.substring(3, 6).equals(String.valueOf(Integer.parseInt(str.substring(3, 6)))) && // 确保DEF是有效的数字
                    str.substring(6).equals(String.valueOf(Integer.parseInt(str.substring(6))))) { // 确保GHI是有效的数字

                int abc = Integer.parseInt(str.substring(0, 3));
                int def = Integer.parseInt(str.substring(3, 6));
                int ghi = Integer.parseInt(str.substring(6));
                if (abc + def == ghi) {
                    String combination = abc + "+" + def + "=" + ghi;
                    combinations.add(combination);

                }
            }
            return;
        }

        for (int i = level; i < numbers.size(); i++) {
            Collections.swap(numbers, level, i);
            current.append(numbers.get(level));
            permute(numbers, level + 1, current, combinations);
            current.deleteCharAt(current.length() - 1);
            Collections.swap(numbers, level, i); // 回溯
        }
    }
}

问题 F: 油田问题

题目描述

输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块。如果两个字符“@”所在的格子相邻(横、竖或者对角线方向),即属于同一个八连块。

输入
多组输入
输入行数m,以及列数n。
然后输入*和@
1<=n,m<=100
输出
联通块个数
样例输入 Copy
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
样例输出 Copy
2
import java.util.Scanner;

public class Main {
    static char[][] a;//存储输入的字符
    static int m;//输入的行
    static int n;//列
    static int[][] a_id;//标记@所在区域连块
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
          m = scanner.nextInt();
          n = scanner.nextInt();
         a=new char[m][n];
          a_id = new int[m][n];
          int id =0;//记录有多少@连块
         for (int i=0;i<m;i++){
             String str = scanner.next();
             for (int j=0;j<n;j++){
                 a[i][j] = str.charAt(j);
             }

         }

            for (int i=0;i<m;i++)//遍历每一个字符
                for (int j=0;j<n;j++)
                   if (a_id[i][j]==0&&a[i][j]=='@')
                       solve(i,j,++id);
            System.out.println(id);

        }
    }
    static void solve(int r, int c, int id){
        if (r<0||r>=m||c<0||c>=n||a_id[r][c]>0||a[r][c]!='@') return;
        else {
            a_id[r][c]=id;
            for (int dr=-1;dr<=1;dr++){
                for (int dc=-1;dc<=1;dc++){
                    if (dr!=0||dc!=0)
                        solve(r+dr,c+dc,id);//将找到的@符号的周围所在的格子相邻(横、竖或者对角线方向)的@的id标记为同一个
                }
            }
        }
    }
}

  • 38
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值