蓝桥杯 9数算式 (回溯法)

一:问题
标题:9数算式
观察如下的算式:
9213 x 85674 = 789314562
左边的乘数和被乘数正好用到了1~9的所有数字,每个1次。
而乘积恰好也是用到了1~9的所有数字,并且每个1次。
请你借助计算机的强大计算能力,找出满足如上要求的9数算式一共有多少个?
注意:
总数目包含题目给出的那个示例。
乘数和被乘数交换后作为同一方案来看待。

二:分析
需要找出符合要求的算式,首先需要找到所有满足9数算式要求的乘数被乘数字符串(要求可以描述为:①字符串分割为乘数和被乘数后用到了1-9各一次②乘积也用到了1-9各一次)。
找字符串的过程类似于深度优先搜索的思想,最终的目标是使字符串长度达到9且用到了1-9各一次。每次搜索不找到一条完整的“路径”就不停下来。可以定义一个状态数组来记录1-9数字的使用情况,在dfs的过程中,每次访问到一个数之后,将其标记为true,“使用”完毕后再将其状态改回为false。

dfs过程(引用自@柏枫杨柳)

https://blog.csdn.net/qq_21158525/article/details/79459378

边界状态:字符串长度达到9

void dfs(String 当前状态)  
    {  
          if(当前状态为边界状态)  
          {  
           检查字符串是否符合要求
            return;  
          }  
          for(i=0;i<n;i++)       //横向遍历解答树所有子节点  
         {  
               //扩展出一个子状态。  
               修改了全局变量  
               if(子状态满足约束条件)  
                {  
                  dfs(子状态)  
               }  
                恢复全局变量     //回溯部分 
             }  
    }

三:代码

package 一七年真题9数算式;
public class Main {
	private static boolean isVisited[] = new boolean[10];
	private static int count = 0;
	public static void main(String[] args){
		String numString="";
		long t=System.currentTimeMillis();
		dfs(numString,0);
		System.out.println(count/2+"\n"+(System.currentTimeMillis()-t)+"ms");  //乘数与被乘数交换视为同一算式
	}
	private static void dfs(String s,int length)
	{
		if(length==9)
		{
			for(int i=1;i<9;i++)
			{
				int multiplier=Integer.parseInt(s.substring(0, i));
				int multiplicand=Integer.parseInt(s.substring(i,9));
				int answer = multiplier*multiplicand;
				if(check(answer))
				{
					count++;
					//System.out.println(multiplier+"×"+multiplicand+"="+answer);
				}
			}
			return;
		}
		for(int i=1;i<10;i++)
		{
			if(isVisited[i]==false)
			{
				isVisited[i]=true;
				dfs(s+i,length+1);
				isVisited[i]=false;
			}
		}
	}
	private static boolean check(int resultNum)
	{
		boolean isVisitedC[] = new boolean[10];
		while(resultNum!=0)
		{
			int numNow=resultNum%10;
			if(numNow<1&&numNow>9)
				return false;
			isVisitedC[numNow]=true;
			resultNum/=10;
		}
		for(int i=1;i<10;i++)
		{
			if(isVisitedC[i]==false)
				return false;
		}
		return true;
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42416780/article/details/85917540