算法设计与分析: 5-24 算m点问题

本文探讨了如何使用回溯法解决算m点问题,即通过加减乘除运算连接k个正整数,使得结果等于m。文章提供了问题描述、Java代码实现,并给出了输入输出示例及参考文献。
摘要由CSDN通过智能技术生成

5-24 算m点问题


问题描述

给定 k 个正整数,用算术运算符“+”,“-”,“*”,“/”将这 k 个正整数连接起来,使最终的得数恰为 m。

对于给定的 k 个正整数,给出计算 m 的算术表达式。

数据输入:
第一行有 2 个正整数 k 和 m,表示给定 k 个正整数,且最终的得数恰为 m。接下来的 1 行中,有 k 个正整数。


Java

package Chapter5HuiSuFa;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

public class SuanMDian {
   

    private static int kk,mm;

    private static double[] d;
    private static boolean found;

    private static Set<String> answer;
    private static double[][] r;

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

        while (true){
            kk = input.nextInt();
            mm = input.nextInt();

            r = new double[kk][kk+1];
            d = new double[kk+1];
            answer = new HashSet<>();

            for(int i=1; i<=kk; i++)
                d[i] = input.nextDouble();

            found = false;

            search(kk,d);

            Iterator<String> it = answer.iterator();
            while (it.hasNext()){
                System.out.println(it.next());
            }
            if(!found)
                System.out.println("No answer!");
        }
    }

    private static void search(int k, double[] d){
        int i,j,m,t;
        double a, b;
        double[] e = new double[kk+1];
        if(k == 1){
            if((int)((d[1]-mm)*10000) == 0){
                outanswer();
                found = true;
            }
        }else {
            for(i=1; i<=k-1; i++)
                for(j=i+1; j<=k; j++){
                    a = d[i];
                    b = d[j];
                    if(a < b) {
  double tmp=a;a=b;b=tmp;}
                    for(m=1,t=0; m<=k; m++)
                        if(m!=i && m!=j)
                            e[++t] = d[m];
                    r[kk+1-k][1] = a;
                    r[kk+1-k][3] = b;
                    r[kk+1-k][4] = -1;
                    for(m=1; m<=6; m++){
                        switch (m){
                            case 1: r[kk+1-k][4]=a+b; break;
                            case 2: r[kk+1-k][4]=a-b; break;
                            case 3: r[kk+1-k][4]=a*b; break;
                            case 4: if(b!=0) r[kk+1-k][4]=a/b; break;
                            case 5: if(a!=0) r[kk+1-k][4]=b/a; break;
                            case 6: r[kk+1-k][4]=b-a; break;
                        }
                        r[kk+1-k][2] = m;
                        if(r[kk+1-k][4] != -1){
                            e[t+1] = r[kk+1-k][4];
                            search(k-1,e);
                        }
                    }
                }
        }
    }

    private static void outanswer(){
        StringBuffer msg = new StringBuffer();
        for(int i=1; i<kk; i++){
            switch ((int)(r[i][2])){
                case 1: msg.append(((r[i][1]<0)?"(":"")+r[i][1]+((r[i][1]<0)?")":"")+"+"+((r[i][3]<0)?"(":"")+r[i][3]+((r[i][3]<0)?")":"")); break;
                case 2: msg.append(((r[i][1]<0)?"(":"")+r[i][1]+((r[i][1]<0)?")":"")+"-"+((r[i][3]<0)?"(":"")+r[i][3]+((r[i][3]<0)?")":"")); break;
                case 3: msg.append(((r[i][1]<0)?"(":"")+r[i][1]+((r[i][1]<0)?")":"")+"*"+((r[i][3]<0)?"(":"")+r[i][3]+((r[i][3]<0)?")":"")); break;
                case 4: msg.append(((r[i][1]<0)?"(":"")+r[i][1]+((r[i][1]<0)?")":"")+"/"+((r[i][3]<0)?"(":"")+r[i][3]+((r[i][3]<0)?")":"")); break;
                case 5: msg.append(((r[i][3]<0)?"(":"")+r[i][3]+((r[i][3]<0)?")":"")+"/"+((r[i][1]<0)?"(":"")+r[i][1]+((r[i][1]<0)?")":"")); break;
                case 6: msg.append(((r[i][3]<0)?"(":"")+r[i][3]+((r[i][3]<0)?")":"")+"-"+((r[i][1]<0)?"(":"")+r[i][1]+((r[i][1]<0)?")":"")); break;
            }
            msg.append("="+r[i][4]+"; ");
        }
        String ans = new String(msg);
        if(!answer.contains(ans))
            answer.add(ans);
    }
}

Input & Output

5 125
2 2 12 3 7
7.0*3.0=21.0; 21.0*12.0=252.0; 252.0-2.0=250.0; 250.0/2.0=125.0; 
12.0*3.0=36.0; 36.0*7.0=252.0; 252.0-2.0=250.0; 250.0/2.0=125.0; 
12.0*7.0=84.0; 84.0*3.0=252.0; 252.0-2.0=250.0; 250.0/2.0=125.0; 


5 24
2 2 12 3 7
12.0*7.0=84.0; 2.0*2.0=4.0; 84.0/3.0=28.0; 28.0-4.0=24.0; 
2.0-12.0=-10.0; 7.0*(-10.0)=-70.0; 2.0-(-70.0)=72.0; 72.0/3.0=24.0; 
12.0*7.0=84.0; 84.0/3.0=28.0; 2.0*2.0=4.0; 28.0-4.0=24.0; 
2.0*2.0=4.0; 4.0/12.0=0.3333333333333333; 7.0/0.3333333333333333=21.0; 21.0+3.0=24.0; 
2.0/7.0=0.2857142857142857; 2.0*0.2857142857142857=0.5714285714285714; 12.0/0.5714285714285714=21.0; 21.0+3.0=24.0; 
12.0*3.0=36.0; 7.0*2.0=14.0; 36.0-14.0=22.0; 22.0+2.0=24.0; 
2.0/12.0=0.16666666666666666; 2.0*0.16666666666666666=0.3333333333333333; 7.0/0.3333333333333333=21.0; 21.0+3.0=24.0; 
12.0+2.0=14.0; 14.0*2.0=28.0; 3.0-7.0=-4.0; 28.0+(-4.0)=
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值