原题链接:蓝桥杯历届试题-约数倍数选卡片
解题思路:
   
基本的博弈都可以用递归来求解,这道题由于想不到有效解法,则用 递归+优化
1. 尝试所有走法,把局面交给对手,如果对手的局面是必输,则当前局面必胜;
2. 尝试所有走法后,还是赢不了那 当前局面比输
    
递归思路:
dfs(局面s){
尝试走一步s变成s1,把s1交给对手
如果存在一个s1局面必输:返回赢了;
返回必输;
}
不优化 只有50%成绩
优化思路:1.优先当前可选的数字大的卡片(数字越大,则约倍数在100内越少,所以递归的层数就越少)
2.常数优化,递归之前预处理每张卡片的下一次可选卡片集合
注意事项:
    这个C语言网不知为什么代码AC不了一直超时17%,我去蓝桥杯官网提交了两次都600msAC了
  
参考代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#define _for(i,a,b) for(int i=a;i<b;i++)
#define _unfor(i,a,b) for(int i=a;i>=b;i--)
#define mset(a,val,n) for(int i=0;i<n;i++)a[i]=val;
#define FO freopen("out.txt","w",stdout)
#define RI(a) scanf("%d",&a)
using namespace std;
typedef long long LL;
int a[111],b[111],c='A';
vector<int> G[111];
int ri(){
    int x=0;
    while(!isdigit(c))if((c=getchar())=='\n')return 0;
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x;
}
int dp(int i){
    if(!a[i])return 0;
    a[i]--;
    int len=G[i].size();
    _for(k,0,len){
        int j=G[i][k];
        if((!(i%j)||!(j%i))&&a[j])
        if(!dp(j)){a[i]++;return 1;}
    }
    a[i]++;
    return 0;
}
int main(){
    int x;
    while(x=ri()){
        a[x]++;
        if(c=='\n')break;
    }
    //预处理
    _for(i,1,101)
        _unfor(j,100,1)if((!(i%j)||!(j%i))&&a[j])
            G[i].push_back(j);
    //
    while(x=ri()){
        b[x]++;
        if(c=='\n')break;
    }
    _for(i,1,101)if(b[i])
        if(!dp(i)){printf("%d\n",i);return 0;}
    printf("%d\n",-1);
    return 0;
}0.0分
5 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
 
发表评论 取消回复