解题思路:dfs+博弈论,具体看代码注释
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class 约数倍数选卡片 {
static int numA[]=new int[105];
static ArrayList<Integer>[] listA=new ArrayList[105];
static ArrayList<Integer> listB=new ArrayList<Integer>();
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
String s1=sc.nextLine();
String s2=sc.nextLine();
sc.close();
String s11[] =s1.split(" ");
String s22[]=s2.split(" ");
for(int i=0;i<s11.length;i++) {
int tee=Integer.parseInt(s11[i]);
numA[tee]++;//用下标来存储数字,用值来存储相应的数字有几个
}
for(int i=0;i<s22.length;i++) {
listB.add(Integer.parseInt(s22[i]));
}
Collections.sort(listB);
//实例化listA[i],用来存放卡片的约数或倍数
for(int i=1;i<105;i++) {
listA[i]=new ArrayList<Integer>();
}
//该步操作是将卡片中每个卡片的约数或倍数存放起来,存到listA中
for(int i=1;i<=100;i++) {
if(numA[i]!=0) {//1~100的遍历,寻找剩余卡片中的数,如果存在
numA[i]--;//则该数取出
for(int j = 1;j <= 100;j++)//取出卡片后,继续看剩余卡片是否存在,并且将值为i的卡片的约数或倍数卡片值存放起来
if(numA[j] != 0 && (i % j == 0 || j % i == 0))
listA[i].add(j);//listA[i]存放卡片中的能够是所选卡片的约数或倍数的数
numA[i]++;
}
}
//选择每个可能的卡片,进行深搜
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");//如果能到这步,说明对手不存在输的情况,则我输
}
private static int dfs(int[] numA2, ArrayList<Integer>[] listA2, 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)//自己选如果返回-1,那就意味着没得选了,我输了
return 1;
}
}
return -1;//返回-1,说明没有符合条件的卡片了
}
}