算法笔记_184:历届试题 约数倍数选卡片(Java)

Posted 舞动的心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法笔记_184:历届试题 约数倍数选卡片(Java)相关的知识,希望对你有一定的参考价值。

目录

1 问题描述

2 解决方案

 


1 问题描述

问题描述
  闲暇时,福尔摩斯和华生玩一个游戏:
  在N张卡片上写有N个整数。两人轮流拿走一张卡片。要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数。例如,某次福尔摩斯拿走的卡片上写着数字“6”,则接下来华生可以拿的数字包括:
  1,2,3, 6,12,18,24 ....
  当轮到某一方拿卡片时,没有满足要求的卡片可选,则该方为输方。
  请你利用计算机的优势计算一下,在已知所有卡片上的数字和可选哪些数字的条件下,怎样选择才能保证必胜!
  当选多个数字都可以必胜时,输出其中最小的数字。如果无论如何都会输,则输出-1。
输入格式
  输入数据为2行。第一行是若干空格分开的整数(每个整数介于1~100间),表示当前剩余的所有卡片。
  第二行也是若干空格分开的整数,表示可以选的数字。当然,第二行的数字必须完全包含在第一行的数字中。
输出格式
  程序则输出必胜的招法!!
样例输入
2 3 6
3 6
样例输出
3
样例输入
1 2 2 3 3 4 5
3 4 5
样例输出
4
 

 

 

 


2 解决方案

 

 

具体代码如下:

 

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class Main {
    
    public int dfs(int[] numA, ArrayList<Integer>[] listA, int start) {
        for(int i = listA[start].size() - 1;i >= 0;i--) {
            if(numA[listA[start].get(i)] > 0) {
                 numA[listA[start].get(i)]--;
                int t = dfs(numA, listA, listA[start].get(i));
                numA[listA[start].get(i)]++;
                if(t == -1)
                    return 1;
            }    
        }
        return -1;
    }
    
    
    public void getResult(String A, String B) {
        int[] numA = new int[105];
        @SuppressWarnings("unchecked")
        ArrayList<Integer>[] listA = new ArrayList[105];
        for(int i = 1;i < 105;i++)
            listA[i] = new ArrayList<Integer>();
        ArrayList<Integer> listB = new ArrayList<Integer>();
        String[] arrayA = A.split(" ");
        String[] arrayB = B.split(" ");
        for(int i = 0;i < arrayA.length;i++) {
            int a = Integer.valueOf(arrayA[i]);
            numA[a]++;
        }
        for(int i = 1;i <= 100;i++) {
            if(numA[i] != 0) {
                numA[i]--;
                for(int j = 1;j <= 100;j++)
                    if(numA[j] != 0 && (i % j == 0 || j % i == 0))
                        listA[i].add(j);
                numA[i]++;
            }
        }
        for(int i = 0;i < arrayB.length;i++) {
            int b = Integer.valueOf(arrayB[i]);
            listB.add(b);
        }
        Collections.sort(listB);
        for(int i = 0;i < listB.size();i++) {
            numA[listB.get(i)]--;
            int t = dfs(numA, listA, listB.get(i));
            numA[listB.get(i)]++;
            if(t == -1) {
                System.out.println(listB.get(i));
                return;
            }
        }
        System.out.println("-1");
        return;
    }
    
    public static void main(String[] args) {
        Main test = new Main();
        Scanner in = new Scanner(System.in);
        String A = in.nextLine();
        String B = in.nextLine();
        test.getResult(A, B);
    }
}

 

 

 

 

 

 

 

参考资料:

   1. 蓝桥杯历届试题——约数倍数选卡片(博弈论+dfs)

 

以上是关于算法笔记_184:历届试题 约数倍数选卡片(Java)的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯 约数倍数选卡片

算法笔记_183:历届试题 九宫重排(Java)

算法笔记_160:算法提高 约数个数(Java)

算法中数学相关知识-倍数约数完全数质数最小公倍数

最大公倍数

整除理论例题选做