历届试题 约数倍数选卡片

问题描述

  闲暇时,福尔摩斯和华生玩一个游戏:
  在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
思路:
 思路:直接dfs搜索各种后继状态,抓住博弈的性质:对于必胜状态,必有一个后继状态是必败的,对于必败状态所有后继状态都是必胜的。假设当前选择是必胜态,那么后手的所有选择都必须是P态才行。
和nim游戏一个思想,把图画出来就好理解了,先手保证后手怎么选先手都有获胜的方式,后手保证先手至少先手有一种方式选择才可以保证先手胜,否则先手输
代码如下:
 1 #include
 2 using namespace std;
 3 int array[1000];
 4 int Aarray[1000];
 5 int array1[1000];
 6 int t1=0;
 7 int t2=0;
 8 int s=0;
 9 int flag=1;
10 int DFS(int n)
11 {
12     int l;
13    if(s==0 || s%2==0){
14         flag=1;
15         int a=1;
16     for(int i=t1-1;i>=0;i--){
17             l=0;
18     if((n%array[i]==0 || array[i]%n==0) &&Aarray[i]==0 ){
19         l++;
20         Aarray[i]=1;
21         s++;
22         a=DFS(array[i]);
23         s--;
24         Aarray[i]=0;
25         if(a==0){ flag=0;  break;}//决策失败
26     }
27    }
28    if(a==0) return flag;
29    if(l==0){
30     return 1;
31    }
32    }else{
33        flag=0;
34        int a=0;
35     for(int i=t1-1;i>=0;i--){
36          l=0;
37         if((n%array[i]==0 || array[i]%n==0) &&Aarray[i]==0){
38             l++;
39         Aarray[i]=1;
40         s++;
41         a=DFS(array[i]);
42         s--;
43         Aarray[i]=0;
44         if(a==1){ flag=1; break;}
45         }
46     }
47     if(a==1) return flag;
48     if(l==0){
49         return 0;
50     }
51    }
52    return flag;
53 }
54 int main()
55 {
56    //ios::sync_with_stdio(0),cin.tie(0);
57     memset(array1,0,sizeof(array1));
58     memset(array,0,sizeof(array));
59     memset(Aarray,0,sizeof(Aarray));
60     int num;
61     char c;
62     while(true){
63         cin >>num;
64       //  scanf("%d",num);
65         c=getchar();
66         array[t1++]=num;
67         if(c=='\n') break;
68     }
69     while(true){
70         cin >> num;
71         //scanf("%d",num);
72         c=getchar();
73         array1[t2++]=num;
74         if(c=='\n') break;
75     }
76      int m=0;
77      for(int i=0;i){
78 
79        int j;
80        for( j=0;j){
81         if(array[j]==array1[i]){
82             Aarray[j]=1;
83             break;
84         }
85        }
86 
87        int aa= DFS(array1[i]);
88        Aarray[j]=0;
89         if(aa==1){
90           cout << array1[i] << endl;
91           break;
92         }else{
93          m++;
94         }
95      }
96      if(m==t2) cout << "-1" << endl;
97     return 0;
98 }

该代码第四第五组测试数据有点超时,网上有用vector降低时间复杂度的,今天状态不好,看以后再改进把。

 

转载于:https://www.cnblogs.com/henuliulei/p/10505432.html

你可能感兴趣的:(历届试题 约数倍数选卡片)