码迷,mamicode.com
首页 > 其他好文 > 详细

蓝桥杯 约数倍数选卡片

时间:2017-03-13 11:36:43      阅读:518      评论:0      收藏:0      [点我收藏+]

标签:--   递归   init   函数参数   位置   for   状态   ack   cin   

思路:

搜索、博弈论。

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

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

实现:

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

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

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

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

 

蓝桥杯 约数倍数选卡片

标签:--   递归   init   函数参数   位置   for   状态   ack   cin   

原文地址:http://www.cnblogs.com/wangyiming/p/6541500.html

(2)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!