zoukankan      html  css  js  c++  java
  • 蓝桥杯 约数倍数选卡片

    思路:

    搜索、博弈论。

    实现的时候一个剪枝是从较大的数开始选,因为较大的数约数或倍数少一些,搜索的层数少。

    还可以预处理出每个数的约数和倍数,这样搜索的时候不用扫描所有的数。

    实现:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <string>
     5 #include <cstring>
     6 #include <sstream>
     7 #include <vector>
     8 #include <algorithm>
     9 using namespace std;
    10 
    11 const int MAXN = 105;
    12 int a[MAXN], b[MAXN], m = 0;
    13 vector<int> ok[MAXN];
    14 
    15 bool check(int x, int y)
    16 {
    17     int p = min(x, y);
    18     int q = max(x, y);
    19     return !(q % p);
    20 }
    21 
    22 void init()
    23 {
    24     for (int i = 1; i < MAXN; i++)
    25     {
    26         if (a[i])
    27         {
    28             for (int j = 1; j < MAXN; j++)
    29             {
    30                 if (a[j] && check(i, j))
    31                     ok[i].push_back(j);
    32             }
    33         }
    34     }
    35 }
    36 
    37 bool dfs(int last)
    38 {
    39     for (int i = ok[last].size() - 1; i >= 0; i--)
    40     {
    41         int tmp = ok[last][i];
    42         if (a[tmp])
    43         {
    44             a[tmp]--;
    45             bool res = dfs(tmp);
    46             a[tmp]++;
    47             if (!res)
    48                 return true;
    49         }
    50     }
    51     return false;
    52 }
    53 
    54 int main()
    55 {
    56     string x;
    57     int t;
    58     stringstream s;
    59     getline(cin, x);
    60     s << x;
    61     while (s >> t)  a[t]++;
    62     init();
    63     s.clear();
    64     getline(cin, x);
    65     s << x;
    66     while (s >> b[m++]);
    67     m--;
    68     sort(b, b + m);
    69     int * end = unique(b, b + m);
    70     bool flag = true;
    71     for (int i = 0; i < end - b; i++)
    72     {
    73         a[b[i]]--;
    74         bool res = dfs(b[i]);
    75         a[b[i]]++;
    76         if (!res)
    77         {
    78             cout << b[i] << endl;
    79             flag = false;
    80             break;
    81         }
    82     }
    83     if (flag)
    84         cout << -1 << endl;
    85     return 0;
    86 }

    总结:

     必败点:前一个选手将取胜的位置称为必败点。

     必胜点:下一个选手将取胜的位置称为必胜点。

     必胜点和必败点属性:

     (1)所有终结点是必败点。

     (2)从任何必胜点操作,至少有一种方法可以进入必败点。

     (3)无论如何操作,从必败点都只能进入必胜点。

     可以采用递归或递推实现。

     注意函数参数的值传递的过程。

     回溯的时候不要影响标记状态的全局变量,要及时归位。

  • 相关阅读:
    广域网(ppp协议、HDLC协议)
    0120. Triangle (M)
    0589. N-ary Tree Preorder Traversal (E)
    0377. Combination Sum IV (M)
    1074. Number of Submatrices That Sum to Target (H)
    1209. Remove All Adjacent Duplicates in String II (M)
    0509. Fibonacci Number (E)
    0086. Partition List (M)
    0667. Beautiful Arrangement II (M)
    1302. Deepest Leaves Sum (M)
  • 原文地址:https://www.cnblogs.com/wangyiming/p/6541500.html
Copyright © 2011-2022 走看看