48天笔试训练错题——day38

目录

选择题

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

编程题

1. 蘑菇阵

2. 红与黑


选择题

1.

TCP:有连接,可靠传输,面向字节流。

UDP:无连接,不可靠,面向数据报。

TCP 协议和 UDP 协议都是传输层协议。

2.

应用层:针对特定应用规定各层协议,时序,表示等,进行封装。如 HTTP。

表示层:规定数据的格式化表示,数据格式的转换。

会话层:规定通信时序,数据交换的定界,同步,创建检查点等。

传输层:节点(端口)之间可靠地分发数据包。

网络层:路由选择(IP 寻址),拥塞控制。

数据连接层:检错与纠错(CRC 码),多路访问,寻址。

物理层:定义机械特性,电气特性。

3.

应用层:文件传输协议(FTP),远程登录协议(Telnet),电子邮件协议(SMTP),网络文件服务协议(NFS),网络管理协议(SNMP),域名解析协议(DNS)。

传输层:TCP,UDP 协议。

网络层:IP,ICMP,ARP,RARP。

PPP 是数据链路层协议。

4.

5.

6.

URL 又名统一资源定位符,方便确定一个资源,并表示它在哪里,可以使用大写字母。

80 端口是 HTTP 地端口。

URL 格式:
protocol://hostname[:port]/path/[;parameters][?query]#fragment

7.

8.

应用层:文件传输协议(FTP),远程登录协议(Telnet),电子邮件协议(SMTP),网络文件服务协议(NFS),网络管理协议(SNMP),域名解析协议(DNS)。

传输层:TCP,UDP 协议。

网络层:IP,ICMP,ARP,RARP。

9.

211.168.15.192/26     ( /26  表示子网掩码使用了 26 个高位比特位 )

IP 地址   :11010011  10101000  00001111  11000000

子网掩码:11111111    11111111   11111111   11000000

所以主机号范围使用 6 个比特位。

211.168.15.160/27

IP 地址   :11010011  10101000  00001111  10100000

子网掩码:11111111   11111111    11111111   11100000

所以主机号范围使用 5 个比特位。

211.168.15.128/27

IP 地址   :11010011  10101000  00001111  10000000

子网掩码:11111111   11111111    11111111   11100000

所以主机号范围使用 5 个比特位。

如上,能发现三个 IP 地址地前 25 位是一样的,所以聚合前 25 位比特位 ,剩下 7 位就作为主机号存在。211.168.15.128/25

所以网段号是 211.168.15.128,2^7 = 128,

所以子网范围是 211.168.15.128 - 211.168.15.255。除去全 0 (网段号)和全 1 (广播号)后,剩下 126 个。

10.

编程题

1. 蘑菇阵

这道题,我们可以用动态规划的方法来做,首先根据题目来设计 dp[i][j] 的含义。

如题,题目要求计算从 (1,1) 走到 (n,m) 不遇到蘑菇的概率,那么 dp[i][j] 就是从 (1,1) 走到 (i,j) 不遇到蘑菇的概率。然后再来推算状态转移方程,dp[i][j] = ?,看题,题目规定只能向右走和向下走,那么要到达 (i,j) 这个位置,只能是从上方下来的,或者是从左方过来的,所以 dp[i][j] 等于从 dp[i - 1][j] 向下走的概率,再加上从 dp[i][j - 1] 向右走的概率,一般来说只能走两个方向,概率就是 0.5,但是也有特殊情况,那就是在边界 i == n 和 j == m 的情况,只有一种选择,只能朝右走或者朝下走,所以概率要根据边界情况来决定,则最终 dp[i][j] = dp[i - 1][j] * (j == m ? 1 : 0.5) + dp[i][j - 1] *(i == n ? 1 : 0.5); 如果 (i,j) 是蘑菇的话,那么 dp[i][j] = 0,然后就是初始化,dp[1][1] = 0,最后返回 dp[n][m] 即可。

代码实现:

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int n = in.nextInt();
            int m = in.nextInt();
            int k = in.nextInt();

            // dp[i][j] 表示从 (1,1) 走到 (i,j) 的不遇到蘑菇概率
            double[][] dp = new double[n + 1][m + 1];

            // 用 -1 表示蘑菇位置
            for (int i = 0; i < k; i++) {
                int x = in.nextInt();
                int y = in.nextInt();
                dp[x][y] = -1;
            }

            // 初始化
            dp[1][1] = 1.0;
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    if (i == 1 && j == 1) continue;
                    // 是蘑菇
                    if (dp[i][j] == -1) {
                        dp[i][j] = 0;
                    } else {
                        // 从上边来,如果不是边界,则往下走的概率要乘 0.5
                        double up = dp[i - 1][j] * (j == m ? 1 : 0.5);
                        // 从左边来,如果不是边界,则往右走的概率要乘 0.5
                        double left = dp[i][j - 1] * (i == n ? 1 : 0.5);
                        dp[i][j] = up + left;
                    }
                }
            }

            System.out.printf("%.02f\n", dp[n][m]);
        }
    }
}

2. 红与黑

像上面这种能往四个方向走的题目一般都是用深度优先遍历,深搜的过程都差不多,就是将瓷砖数组,标记数组,m,n,i,j 作为 dfs 的参数,然后定义一个静态成员变量 count 记录能遍历到的黑色瓷砖,然后进入 dfs 就先判断数组是否越界,是否是已经遍历过的格子,和是否是白色瓷砖,如果满足以上条件,那就直接返回,如果不是,那么则说明是第一次遇到黑色瓷砖,那就 count++,然后再将现在的格子标记一下,然后继续往上下左右四个方向走,就是这里不需要回溯,最后等 dfs 结束,再输出 count 即可,但是有一点需要注意,因为 count 是静态成员变量,所以只会初始化一次,所以成员都是共享的,为了防止 count 叠加多次测试用例的结果,则需要在进行 dfs 前将 count 置为 0.

代码实现:

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    // 记录深搜黑色瓷砖数量
    public static int count = 0;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int m = in.nextInt();
            int n = in.nextInt();

            // 记录起始位置
            int x = -1;
            int y = -1;
            // 接收瓷砖的数组
            char[][] arr = new char[m][n];
            // 标记走过的格子的数组
            boolean[][] flg = new boolean[m][n];
            for (int i = 0; i < m; i++) {
                String str = in.next();
                arr[i] = str.toCharArray();

                if (str.contains("@")) {
                    for (int j = 0; j < n; j++) {
                        char c = arr[i][j];
                        if (c == '@') {
                            x = i;
                            y = j;
                        }
                    }
                }
            }

            // 防止 count 叠加多次测试用例的运行结果(static 变量只会实例化一次)
            count = 0;

            dfs(arr, flg, x, y, m, n);
            System.out.println(count);
        }
    }


    public static void dfs(char[][] arr, boolean[][] flg, int i, int j, int m, int n) {
        // 越界或格子已经走过或白色瓷砖
        if (i < 0 || i >= m || j < 0 || j >= n || flg[i][j] || arr[i][j] == '#') {
            return;
        }
        count++;
        flg[i][j] = true;
        // 再往四个方向走
        dfs(arr, flg, i - 1, j, m, n);
        dfs(arr, flg, i + 1, j, m, n);
        dfs(arr, flg, i, j - 1, m, n);
        dfs(arr, flg, i, j + 1, m, n);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值