洛谷算法记录-P1013

题目:P1013 [NOIP1998 提高组] 进制位

解题思路:

        1:根据题干要求:9>=N>=3 , 且字母不重复,所以是2进制到8进制之间的数据

        2:假设N=5,即输入四进制数据,则S(i,0)列必是:0,1,2,3;并作为每行的开头数字(行顺序可先不在意),每行简单的和每列数字做下加法如下:

       1开头的行(10)                     2开头的行(10,11)                3开头的行(10,11,12)

        1+1 = 02        ​​​​​​​                         2+1 = 03        ​​​​​​​                   3+0 = 03          ​​​​​​​
        1+2 = 03                                 2+2 = 10                           3+1 = 10                                 
      
  1+3 = 10     ​​​​​​​                            2+3 = 11           ​​​​​​​                3+2 = 11                      
                                                                                                3+3 = 12     

        识别行开头的逻辑:根据上面规律发现行开头是数字n,则行内出现双位数的数量即n;反之出现了几个双位数就是几开头。

         3:题干其他判断逻辑:

                一:斜对角对称

                二:第一列或第一行内容不重复

                三:S[i,0]值 + S[0,j]值 =  S[i,j]   //S[i,j]字符根据位数做切割,并把十位字符数乘以进制数,再加上个位数值

编码解决:


import java.util.*;

public class Main {


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

    public static void run() {
        try {  //初始化输入
            Scanner scanner = initScanner();
            //读取整数
            Integer n = readNumnber(scanner, 3, 9);
            //根据整数构建二维数组
            String[][] datas = read2Array(scanner, n);
            //统计 - 每个字符出现次数
            Map<String, String> rs = new LinkedHashMap<>();

            //校验数据行
            for (int i = 0; i < n; i++) {
                if (!datas[i][0].equals(datas[0][i])) {
                    throw new RuntimeException("不对称");
                }
                if (datas[i][0].length() != 1) {
                    throw new RuntimeException("字母长度不对");
                }
                //统计每个字母行内出现2位长度的字符数量,即当前行字符的数值
                int cnt = 0;
                for (int j = 0; j < n; j++) {
                    if (datas[i][j].length() <= 1) {//2位数
                        continue;
                    }
                    cnt++;
                }
                rs.put(datas[i][0], cnt + "");
            }

            //判断字符是否重复
            if (rs.keySet().size() != n) {
                throw new RuntimeException("数组高度重复");
            }
            //移除加号统计
            rs.remove("+");

            //替换二维数组字符 转 数字
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if ("+".equals(datas[i][j])) {
                        continue;
                    }
                    for (Map.Entry<String, String> entry : rs.entrySet()) {
                        datas[i][j] = datas[i][j].replaceAll("[" + entry.getKey() + "]", entry.getValue());
                    }
                }

                if ("+".equals(datas[i][0])) {
                    continue;
                }

                //数值不能超过进制最大值
                if (Integer.parseInt(datas[i][0]) > n - 2) {
                    throw new RuntimeException("超出进制范围");
                }
            }

            //校验数据行
            for (int i = 1; i < n; i++) {
                for (int j = 1; j < n; j++) {
                    //加法校验(n-1进制)
                    if (datas[i][j].length() <= 1) {//单字符值校验
                        if (Integer.parseInt(datas[i][0]) + Integer.parseInt(datas[0][j]) != Integer.parseInt(datas[i][j])) {
                            throw new RuntimeException("进制加法不通过 n=" + (n - 1) + " i=" + i + ",j=" + j + " -> " + datas[i][j]);
                        }
                    } else {//双位字符值校验
                        String[] ds = datas[i][j].split("");
                        if (Integer.parseInt(datas[i][0]) + Integer.parseInt(datas[0][j]) != Integer.parseInt(ds[0]) * (n - 1) + Integer.parseInt(ds[1])) {
                            throw new RuntimeException("进制加法不通过 n=" + (n - 1) + " i=" + i + ",j=" + j + " -> " + datas[i][j]);
                        }

                    }
                }
            }

            String text = rs.toString().replaceAll("[{}\"]", "").replaceAll(":", "=");
            text = text.replaceAll(",", "");
            System.out.println(text);
            System.out.print(n - 1);
        } catch (RuntimeException e) {
            //e.printStackTrace();
            System.out.print("ERROR!");
        }
    }


    public static Scanner initScanner() {
        return new Scanner(System.in);
    }

    //读取整数行
    public static int readNumnber(Scanner scanner, Integer min, Integer max) {
        int val = Integer.parseInt(scanner.nextLine());
        if (min != null && val < min) {
            throw new RuntimeException("数值" + val + "不能小于" + min);
        }
        if (max != null && val > max) {
            throw new RuntimeException("数值" + val + "不能大于" + max);
        }
        return val;
    }

    //输入读取二维数组
    public static String[][] read2Array(Scanner scanner, int arraySize) {
        String[][] datas = new String[arraySize][arraySize];
        for (int i = 0; i < arraySize; i++) {
            String line = scanner.nextLine();
            if (line == null || line.equals("")) {//如果是最后一行,使用next
                break;
            }
            String[] l = line.split(" ");
            if (l.length != arraySize) {
                throw new RuntimeException("数组长度不对");
            }
            datas[i] = l;
        }
        for (int i = 0; i < datas.length; i++) {
            for (int j = 0; j < datas[i].length; j++) {
                //System.out.print(datas[i][j] + " ");
            }
            //System.out.println("");
        }
        return datas;
    }


}

  
    
    
 

    
  
    
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

WJL_MGQS

本不富裕的收入,还得买服务器

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

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

打赏作者

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

抵扣说明:

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

余额充值