1 条题解

  • 0
    @ 2025-8-24 22:52:31

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar ivyjiao
    复活了

    搬运于2025-08-24 22:52:31,当前版本为作者最后更新于2023-11-17 09:51:39,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    其实题面少了一句话:假设两人都足够聪明,我们给它加上。

    首先,在博弈中,我们明确三个性质:

    • 如果一个状态的后继有一个必败状态,则该状态为必胜状态。
    • 如果一个状态的后继全都是必胜状态,则该状态为必败状态。
    • 不能再取的状态为必败状态(即:不能再取的状态的后继全都是必胜状态)。

    一般的博弈论题都是可以通过这两条从 (0,0)(0,0) 递推出所有状态的,然而这道题每个状态不仅给了四个点,还有五种转移式,根本无法转移。但是数据范围很小,所以我们考虑爆搜加记忆化。

    不知道为什么清空 dp 数组的时候不能用 memset,我在这里寄了十分钟

    根据以上性质,我们可以写出这样一份代码:

    #include<bits/stdc++.h>
    using namespace std;
    int t,a,b,c,d,dp[31][31][31][31];
    bool dfs(int a,int b,int c,int d){
        if(a<0||b<0||c<0||d<0) return 1;//不能再取的状态的后继全都是必胜状态
        if(dp[a][b][c][d]!=-1) return dp[a][b][c][d];
        if(dfs(a-2,b-1,c,d-2)&&dfs(a-1,b-1,c-1,d-1)&&dfs(a,b,c-2,d-1)&&dfs(a,b-3,c,d)&&dfs(a-1,b,c,d-1)) dp[a][b][c][d]=0;//如果一个状态的后继全都是必胜状态,则该状态为必败状态。
        else dp[a][b][c][d]=1;//如果一个状态的后继有一个必败状态,则该状态为必胜状态。
        return dp[a][b][c][d];
    }
    int main(){
        cin>>t;
        while(t--){
            for(int i=0;i<=30;i++) for(int j=0;j<=30;j++) for(int k=0;k<=30;k++) for(int l=0;l<=30;l++) dp[i][j][k][l]=-1;
            cin>>a>>b>>c>>d;
            if(dfs(a,b,c,d)) cout<<"Patrick"<<endl;
            else cout<<"Roland"<<endl;
        }
    }
    
    • 1

    信息

    ID
    8763
    时间
    2000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者