• Gym102220F Mini-game Before Contest(博弈论)


    一般的博弈论都有必败态和必胜态,都是遇到某个状态发现是已经被决定的。

    对于这题,先观察特殊状态,因为题目是个有向图,所以所有出度为0的点都是有特定状态的,因为他没有路可以走

    我们设状态为f[i][j],表示在i这个点,是j行动,我们假定初始态是-1,表示平局,0表示A赢,1表示B赢,b[i]表示某人真的希望赢的那方

    在出度为0的状态决定以后,只需要让他遍历能到当前点的点,暂时记为X,也就是存反向边,因为操作的顺序一定,所以前一个操作的就是i-1(1是前一个是6)

    如果对于前一个操作人在X的期望和这个点相同,那么就可以更改状态,以下都默认是前一个人在X的期望状态

    如果全部能到达X点的期望答案都与X的期望答案相反,那么X就是必败的。

    这样只需要用一个队列就能扩展更新所有状态。

    对于没有更新到状态的,那么就是表示平局情况

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=2e5+10;
    int f[N][10];
    int n,m;
    int b[N],du[N][10];
    string s,t;
    vector<int> num[N];
    int real1[N];
    int pre(int x){
        if(x==1)
            return 6;
        else
            return x-1;
    }
    void solve(){
        queue<pll> q;
        int i,j;
        for(i=1;i<=n;i++){
            if(du[i][1]==0){
                for(j=1;j<=6;j++){
                    if(s[j]=='A'){
                        f[i][j]=1;
                        q.push({i,j});
                    }
                    else{
                        f[i][j]=0;
                        q.push({i,j});
                    }
                }
            }
        }
        while(q.size()){
            auto x=q.front();
            q.pop();
            for(auto e:num[x.first]){
                if(f[e][pre(x.second)]==-1){
                    if(f[x.first][x.second]==b[pre(x.second)]){
                        f[e][pre(x.second)]=b[pre(x.second)];
                        q.push({e,pre(x.second)});
                    }
                    else{
                        du[e][pre(x.second)]--;
                        if(du[e][pre(x.second)]==0){
                            f[e][pre(x.second)]=b[pre(x.second)]^1;
                            q.push({e,pre(x.second)});
                        }
                    }
                }
            }
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        int T;
        cin>>T;
        while(T--){
            cin>>n>>m;
            memset(f,-1,sizeof f);
            memset(du,0,sizeof du);
            int i,j;
            for(i=0;i<=n;i++)
                num[i].clear();
            for(i=1;i<=m;i++){
                int a,b;
                cin>>a>>b;
                num[b].push_back(a);
                for(j=1;j<=6;j++){
                    du[a][j]++;
                }
            }
            cin>>s>>t;
            s=" "+s;
            t=" "+t;
            for(i=1;i<=6;i++){
                real1[i]=s[i]-'A';
                b[i]=(t[i]-'0')^real1[i];
            }
            solve();
            for(i=1;i<=n;i++){
                if(f[i][1]==-1){
                    cout<<'D';
                }
                else if(f[i][1]==1){
                    cout<<'B';
                }
                else{
                    cout<<'A';
                }
            }
            cout<<endl;
        }
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    ReentrantReadWriteLock读写锁的使用
    Exchanger的使用
    CyclicBarrier的用法
    Semaphore的使用
    CountDownLatch的使用
    BlockingQueue的使用
    对字符串操作的各种笔试题
    struts2请求过程源码分析
    shell语法使用
    hibernate调用mysql存储过程
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13939836.html
Copyright © 2020-2023  润新知