• 历届试题 约数倍数选卡片


    问题描述

      闲暇时,福尔摩斯和华生玩一个游戏:
      在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<bits/stdc++.h>
     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=='
    ') break;
    68     }
    69     while(true){
    70         cin >> num;
    71         //scanf("%d",num);
    72         c=getchar();
    73         array1[t2++]=num;
    74         if(c=='
    ') break;
    75     }
    76      int m=0;
    77      for(int i=0;i<t2;i++){
    78 
    79        int j;
    80        for( j=0;j<t1;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降低时间复杂度的,今天状态不好,看以后再改进把。

     
  • 相关阅读:
    STL标准函数库学习小总结
    3 种生成高强度密码的方法
    树莓派使用 OLED 屏显示图片及文字
    一个骚命令防止你的文件被误删除!
    B站,首战告捷!
    10 个提高效率的 Linux 命令别名
    Vim的三款实用插件
    如何高效回退到特定层级目录?
    如何将目录下的脚本一次性全部执行
    数据结构|数组为什么这么快?
  • 原文地址:https://www.cnblogs.com/henuliulei/p/10505432.html
Copyright © 2020-2023  润新知