算法设计与分析: 5-28 虫蚀算式问题

5-28 虫蚀算式问题


问题描述

虫蚀算式是指古书中算式的一部分被虫蛀了。虫蚀算式问题是根据虫蚀算式剩下的数字,逻辑推断被虫蛀了的数字。例如,

43?98650?45+8468?663344445506978 43 ? 98650 ? 45 + 8468 ? 6633 44445506978

其中“?”表示虫蛀的数字。根据此虫蚀算式,容易推断出,第 1 行的 2 个虫蛀数字分 别是 5 和 3,第 2 行的虫蛀数字是 5。
一般情况下,虫蚀算式问题假设,算式中所有数字都被虫蛀了,但是知道虫蚀算式中哪 些数字相同。另外还知道虫蚀算式是 n 进制加法算式。虫蚀算式中的 3 个数都是 n 位数,且允许前导 0。

对于给定的虫蚀算式,编程计算算式中的虫蚀数字。

数据输入:
第 1 行有 1 个正整数 n(n<=26),表示所给的虫蚀算式是 n 进制加法算式。其后 3 行中,每行有 1 个由 n 个大写英文字母组成的字 符串,分别表示虫蚀算式中的 2 个加数及其和。相同的英文字母代表相同的数字。


Java

package Chapter5HuiSuFa;

import java.util.Scanner;

public class ChongShiSuanShi {

    private static class Node{
        int a,b,c;
        Node next;
    }

    private static int n;
    private static int[][] B;
    private static int[] x;
    private static Node[] cut;

    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        while (true){
            n = input.nextInt();

            B = new int[n][3];
            x = new int[n];
            cut = new Node[n];


            for(int j=0; j<3; j++){
                String a = input.next();
                for(int i=0; i'A';
            }

            for(int i=0; i0);
        }
    }

    private static boolean backtrack(int i){
        if(i == n-1){
            if(oka()){
                for(int j=0; j" ");
                return true;
            }else
                return false;
        }else
            for(int j=i; jif(constrain(i) && backtrack(i+1))
                    return true;
                swap(x,i,j);
            }

        return false;
    }

    private static void swap(int[] x, int i, int j){
        int tmp = x[i];
        x[i] = x[j];
        x[j] = tmp;
    }

    private static boolean oka(){
        int carr = 0;
        for(int i=n-1; i>=0; i--){
            int sum = x[B[i][0]]+x[B[i][1]]+carr;
            if(sum%n != x[B[i][2]]) return false;
            carr = sum/n;
        }

        return true;
    }

    private static boolean constrain(int i){
        for(int j=0; j<=i; j++){
            if(vio(cut[j]))
                return false;
        }

        return true;
    }

    private static boolean vio(Node p){
        while (p != null){
            if((x[p.a]+x[p.b])%n != x[p.c] && (x[p.a]+x[p.b]+1)%n != x[p.c])
                return true;
            p = p.next;
        }

        return false;
    }

    private static void construct(){
        Node p;
        for(int i=0; inull;
        for(int i=0; iint maxi = B[i][0];
            for(int j=1; j<3; j++)
                if(maxi < B[i][j])
                    maxi = B[i][j];
            p = new Node();
            p.a = B[i][0];
            p.b = B[i][1];
            p.c = B[i][2];
            p.next = cut[maxi];
            cut[maxi] = p;
        }
    }
}

Input & Output

5
ABCED
BDACE
EBBAA
1 0 3 4 2 



7
BCEFDAG
CABGEDF
GDGFAGG
1 2 4 5 3 0 6 

Reference

王晓东《计算机算法设计与分析》

你可能感兴趣的:(Algorithm,Java,计算机算法设计与分析,回溯法,计算机算法设计与分析)