Blue Bridge Cup Exams - about the number of multiple selected card (Game Theory + DFS)

topic:

Here Insert Picture Description

analysis:

Digital input frequency this question appears more than once may be, for example, input: 1,223,345 (another sample of the title, in the screenshot not cut out), then we can use a num [105] array to store the number of times the number that appears, NUM is stored in the array data of the first row, the second row represents the input data can just get the first selected digital, we use an array AA [105] to store. Aa sort the elements in the array, after which a cycle through each array element aa, represents the upper hand possible to figure out, based on this, use DFS possible to determine the number of escape, if this FLAC occurred during a winning state, then the upper hand this time is doomed to failure, it showed a return false DFS, if the flip-win every time, then the upper hand is to win, the performance return true.

Code:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

const int MAXN = 105;
 //num数组用于存放第一行输入的每一个数的出现次数 aa数组用于存放第二行先手可以先出的牌数
int num[MAXN],aa[MAXN];
vector<int> vec[MAXN]; //vec[i]用于存放在1和100之间并且在num数组中出现过的i的约数或者倍数
int ind;

bool Select(int k)
{
    //这里必须要从vec[k].size()开始,如果从0开始会出现超时(这里不懂为啥超时。。。)
    for(int i=vec[k].size()-1;i>=0;--i)
        if(num[vec[k][i]])
        {
            num[vec[k][i]]--;
            bool ok = Select(vec[k][i]);
            num[vec[k][i]]++;
            if(ok) return false;
        }
    return true;
}

int main()
{
    int x;
    while(true)
    {
        cin >> x;
        num[x]++;
        char ch = getchar();
        if(ch == '\n') break;
    }
    while(true)
    {
        cin >> x;
        aa[++ind] = x;
        char ch = getchar();
        if(ch == '\n') break;
    }
     //对aa数组排序,因为如果先手有必胜态,题目要求的是输出能产生必胜态的最小的数字
    sort(aa+1,aa+ind+1); 
    //下面的循环两层必须都从1到100循环,因为不管是先手还是后手,拿到一张牌之后,都要依据vec来
    //寻找此数的约数或是倍数。
    for(int i=1;i<=100;++i)
        for(int j=1;j<=100;++j)
            if((i%j==0||j%i==0)&&num[j])
                vec[i].push_back(j);
    for(int i=1;i<=ind;++i)
    {
        if(num[aa[i]]) 
        {
            num[aa[i]]--;  //此处表示先出首先出了aa[i]这张牌
            //如果Select(aa[i])返回true,那么说明后手不管出了什么牌,都是必败的,那么此时就可以输出
            //aa[i]并且结束程序
            if(Select(aa[i]))  
            {
                printf("%d\n",aa[i]);
                return 0;
            }
            num[aa[i]]++;  //回溯 这里表示先出aa[i]是必败的,那么判断下一种情况
        }
    }
    printf("-1\n");
    return 0;
}

Published 33 original articles · won praise 2 · Views 1704

Guess you like

Origin blog.csdn.net/weixin_42469716/article/details/104555811