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)无论如何操作,从必败点都只能进入必胜点。

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

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

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

  • 相关阅读:
    file_get_contents高級用法
    php缓存技术常用函数
    php爬虫的两种思路
    jQuery判断文本框是否为空
    Asp.net 实现图片缩放 无水印(方法二)
    C# winform关于DataGridView的一些操作
    PHP判断访问者手机移动端还是PC端的函数
    本地图片显示在网页
    如何安装 Composer
    国内开源镜像站
  • 原文地址:https://www.cnblogs.com/wangyiming/p/6541500.html
Copyright © 2011-2022 走看看