首页 > 其他分享 >【题解】A18536.星光交错的律动

【题解】A18536.星光交错的律动

时间:2024-03-18 09:13:03浏览次数:20  
标签:val vis int 题解 律动 必胜 bool A18536 first

题目跳转

思路:这道题可能跟博弈论有一点关系,没有学习过博弈论做起来应该问题也不大。思考一个问题,先手必胜的前提是什么?

有关更多的内容可以前往:浅谈有向无环图

  • 先手必胜的前提是,在任何一种局面下,先手都有至少一种操作可以使后手处于必败的局面。
  • 若先手进行任何操作后,后手都可以选择必胜的操作,则先手无法必胜。
  • 如果当前玩家无法进行任何操作,那么对手获胜。

整体的思路就是通过递归不断搜索每一种决策情况,判断是否存在必胜的策略。

具体的实现方法:

创建两个函数,名为firstsecond

  1. first(x, y)函数返回当两位玩家分别选择数字xy时,先手是否必胜。
  2. second(x, y)函数返回当两位玩家分别选择数字xy时,后手是否必胜。

两个函数来回交替调用对方,即在first(x, y)函数中调用second(x, y)函数,在second(x, y)中调用first(x, y)。如果存在必胜的策略,返回true,否则返回false。若先手玩家无法再进行操作时,也返回false。

时间复杂度分析:本道题目将通过深度优先搜索DFS的方式来实现,每一层递归模拟某一位玩家的两个决策(将数字乘二或将数字除以三)。因此本道题目的时间复杂度大致为\(O(2^d)\),其中\(d\)表示递归的深度。考虑题目数据范围\(1 <= x, y <= 1000\),递归深度约为\(\log2(\frac{x+y}{2})\),完全可以在限定时间内通过所有的测试点。

参考代码一:

#include <iostream>
#include <cstring>
using namespace std;

int vis[1005];
bool last(int x, int y);

bool first(int x, int y){
    bool isEnd, p1, p2;
    isEnd = p1 = p2 = true;
    if (x * 2 <= 1000 && !vis[x * 2]){
        isEnd = false;
        vis[x * 2] = 1;
        p1 = last(x*2, y);
        vis[x * 2] = 0;
    }
    if (x % 3 == 0 && !vis[x / 3]){
        isEnd = false;
        vis[x / 3] = 1;
        p2 = last(x / 3, y);
        vis[x / 3] = 0;
    }
    if (isEnd) return false;
    // 如果后手有一条方案会必死,那么先手就一定赢。
    return !(p1 && p2);  
}

bool last(int x, int y){
    bool isEnd, p1, p2;
    isEnd = p1 = p2 = true;
    if (y * 2 <= 1000 && !vis[y * 2]){
        isEnd = false;
        vis[y * 2] = 1;
        p1 = first(x, y * 2);
        vis[y * 2] = 0;
    }
    if (y % 3 == 0 && !vis[y / 3]){
        isEnd = false;
        vis[y / 3] = 1;
        p2 = first(x, y / 3);
        vis[y / 3] = 0;
    }
    if (isEnd) return false;
    return !(p1 && p2);  
}

int main(){
    int t, x, y;
    cin >> t;
    while(t--){
        memset(vis, 0, sizeof vis);
        cin >> x >> y;
        if (first(x, y)) cout << "Macw07" << endl;
        else cout << "Penelope_77" << endl;
    }
    return 0;
}

参考代码二:

  1. decision(r)函数返回当两位玩家分别选择数字val[0]val[1]时,r选手(先手为0,后手为1)是否必胜。
#include <iostream>
#include <cstring>
using namespace std;

int vis[1005];
int val[5];

bool decision(int r){
    bool isEnd, p1, p2;
    isEnd = p1 = p2 = true;
    if (val[r] * 2 <= 1000 && !vis[val[r] * 2]){
        isEnd = false;
        val[r] *= 2;
        vis[val[r]] = 1;
        p1 = decision(!r);
        vis[val[r]] = 0;
        val[r] /= 2;
    }
    if (val[r] % 3 == 0 && !vis[val[r] / 3]){
        isEnd = false;
        val[r] /= 3;
        vis[val[r]] = 1;
        p2 = decision(!r);
        vis[val[r]] = 0;
        val[r] *= 3;
    }
    if (isEnd) return false;
    return !(p1 && p2);  
}

int main(){
    int t, x, y;
    cin >> t;
    while(t--){
        memset(vis, 0, sizeof vis);
        cin >> x >> y;
        val[0] = x;
        val[1] = y;
        if (decision(0)) cout << "Macw07" << endl;
        else cout << "Penelope_77" << endl;
    }
    return 0;
}

标签:val,vis,int,题解,律动,必胜,bool,A18536,first
From: https://www.cnblogs.com/Macw07/p/18079605

相关文章

  • 【题解】A18537.我心中珍藏的游戏
    题目跳转思路:题目问最多可以获得的额外伤害,其实就是询问在这些技能中,如何怎样选取一个最优的发动技能顺序使得攻击加成最大。我们可以把每一个技能看作成一个图的顶点,把每一个攻击加成看作图的边,权制为\(Ei,j\)。由于\(Ei,j\)与\(Ej,i\)相等,则可以将这个图视为无向图。可以样样......
  • 【题解】P2627 [USACO11OPEN] Mowing the Lawn G
    【题解】P2627[USACO11OPEN]MowingtheLawnG题目跳转数据量比较大,暴力肯定是不行的。只能考虑用动态规划的方式来做。这道题有许多dp设计的思路,这里提供两个:方法一:普通状态设计定义\(dp[i][1/0]\)表示截止遍历到第\(i\)个元素时,选择第\(i\)个元素或不选第\(i\)个元素可以......
  • cfRound933div3-E题解
    E-RudolfandkBridges题意:选择的桥在连续的行中,每个桥的支架安装位置是可以不一样的.做法:赛时也感觉也感觉是dp,但是害怕dp,就选择了逃避.往贪心方向想,认为每次到了每个跳板都要跳到最远距离,实际上这样是不行的.很明显,可能存在近一点的点花费更少。实际上是dp,而且也不......
  • [ABC258F] Main Street 题解
    题意:你要在平面直角坐标系中行走,每一步可以上下左右四个方向任意移动$1$,耗时$k$秒。特别地,存在若干条快速通道,若该步起点和终点均满足$x\equiv0\pmod{B}$或$y\equiv0\pmod{B}$,则认为该步是在快速通道上进行,仅需耗时$1$秒。询问从$(S_x,S_y)$到$(G_x,G_y)$最......
  • P3939 数颜色 题解
    题目链接:数颜色经典题目了,暴力数据结构随便过,不过这种不带修的单个颜色的数量查找有个经典的做法:分桶+二分。具体的为每个颜色分桶,记录有序下标,这样就可以二分出\([l,r]\)上的下标个数。对于一次交换来说,如果相邻的颜色相同那么并不会发生交换,如果不同那么就发生交换,由于下标在......
  • P10218 [省选联考 2024] 魔法手杖 题解
    Description给定\(a_1,a_2,\dots,a_n\)以及\(b_1,b_2,\dots,b_n\),满足\(a_i\in[0,2^k-1]\)以及\(b_i\geq0\),你需要给出\(S\subseteq\{1,2,\dots,n\}\)以及\(x\in[0,2^k-1]\)满足以下条件:\(\sum\limits_{i\inS}b_i\leqm\);满足以上条件的前提下,最大化\......
  • P2746 [USACO5.3] 校园网Network of Schools 题解
    题目链接:校园网NetworkofSchools这个题得翻译下题目意思才知道在干嘛,题目一开始表明了这个是一个有向图,因为边是单向的。其次关于第一个问题:基于一个事实,如果有\(x\rightarrowy\rightarrowz\),那么只需要\(x\)接受协议,它所在的\(scc\)强连通分量上的点一定都能不需要......
  • AT_abc345_c [ABC345C] One Time Swap 题解
    题目传送门解法对于\(S_{i}\),设\(num_{S_{i}}\)表示\(S_{i+1\simn}\)中\(S_{i}\)出现的次数,则\(S_{i}\)对答案产生的贡献为\(n-i-num_{S_{i}}\)。注意原串在存在两个相同的元素的时候,也要统计在内。代码#include<bits/stdc++.h>usingnamespacestd;#definell......
  • P2163 [SHOI2007] 园丁的烦恼 题解
    题目链接:园丁的烦恼挺经典的题目,转化成二维数点去做这玩意和常规的偏序计数问题有区别:转化为求\(a\lex\leb\\&\&\c\ley\led\)的数量,这种就别想着拆来拆去了,这种权值类带偏序计数类问题,是经典的可差性问题,我们计:\(ans(x,l,r)\)表示\(t\lex,l\ley\ler\)的数......
  • P3302 [SDOI2013] 森林 题解
    题目链接:森林有意思的树上可持久化线段树变形题,建议先看这个:P2633Countonatree题解对于本题而言,我们重新阐述树上可持久化线段树的核心思想,对于点路径/边路径上的第\(k\)大问题,我们使用树上前缀和问题的思想,将其转化为可差性问题:一条路径上的权值线段树可以拆分为几棵权......