zoukankan      html  css  js  c++  java
  • 怀旧游戏 题解(逆向bfs打表博弈)

    题目链接

    题目思路

    一直不太会这种有环的博弈打表,今天学到了新知识

    处理出每个点的前驱节点,找出所有必败点,然后转移,确定状态后再放入队列,太秒了

    (f[i][j][k][l]) 表示先手手上的数字是 (i, j),后手手上的数字是 (k, l) 时,先手的胜负情况。初始先手必败的情况比较好处理((k)(l) 是 0,意味着先手已经输了),接着反向 bfs,对于一个状态,如果它存在一个先手必败的后续状态,则这个状态先手必胜;如果它所有的后续状态都是先手必胜的,则这个状态先手必败。
    对于无法确定胜负的状态,都是平局。

    直接放官方题解和官方代码

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int f[11][11][11][11], c[10001][4], b[11][11][11][11];
    int test, a1, a2, b1, b2;
    
    struct node {
    	int a1, a2, b1, b2;
    };
    
    vector<node> a[11][11][11][11];
    
    int main() {
    	for (int i = 1; i <= 9; i++)
    		for (int j = 1; j <= 9; j++)
    			for (int k = 1; k <= 9; k++)
    				for (int l = 1; l <= 9; l++) {
    					node res;
    					res.a1 = i; res.a2 = j;
    					res.b1 = k; res.b2 = l;
    					a[k][l][(i + j) % 10][j].push_back(res);
    					a[k][l][(i + k) % 10][j].push_back(res);
    					a[k][l][(i + l) % 10][j].push_back(res);
    					a[k][l][i][(j + i) % 10].push_back(res);
    					a[k][l][i][(j + k) % 10].push_back(res);
    					a[k][l][i][(j + l) % 10].push_back(res);
    				}
    	memset(f, 0, sizeof(f));
    	int head = 0;
    	for (int i = 1; i <= 9; i++)
    		for (int j = 1; j <= 9; j++)
    			for (int k = 1; k <= 9; k++) {
    				f[i][j][k][0] = 2;
    				c[++head][0] = i; c[head][1] = j;
    				c[head][2] = k; c[head][3] = 0;
    				f[i][j][0][k] = 2;
    				c[++head][0] = i; c[head][1] = j;
    				c[head][2] = 0; c[head][3] = k;
    			}
    	for (int l = 1; l <= head; l++) {
    		int a1 = c[l][0], a2 = c[l][1], b1 = c[l][2], b2 = c[l][3];
    		int v = f[a1][a2][b1][b2];
    		if (v == 2) {
    			for (auto i : a[a1][a2][b1][b2])
    				if (!f[i.a1][i.a2][i.b1][i.b2]) {
    					//printf("!
    ");
    					f[i.a1][i.a2][i.b1][i.b2] = 1;
    					c[++head][0] = i.a1; c[head][1] = i.a2;
    					c[head][2] = i.b1; c[head][3] = i.b2;
    				}
    		} else {
    			for (auto i : a[a1][a2][b1][b2])
    				if (!f[i.a1][i.a2][i.b1][i.b2]
    				&& ++b[i.a1][i.a2][i.b1][i.b2] == 6) {
    					f[i.a1][i.a2][i.b1][i.b2] = 2;
    					c[++head][0] = i.a1; c[head][1] = i.a2;
    					c[head][2] = i.b1; c[head][3] = i.b2;
    				}
    		}
    	}
    	scanf("%d", &test);
    	for (; test--; ) {
    		scanf("%d%d%d%d", &a1, &a2, &b1, &b2);
    		if (f[a1][a2][b1][b2] == 1)
    			printf("Alice
    ");
    		else
    			if (f[a1][a2][b1][b2] == 2)
    				printf("Bob
    ");
    			else
    				printf("Tie
    ");
    	}
    }
    
    
    不摆烂了,写题
  • 相关阅读:
    桥牌笔记:三个输墩压缩为一个
    读书笔记2013第7本:《杠杆阅读术》
    读书笔记2013第6本:《棋与人生》(一)
    《Two Dozen Short Lessons in Haskell》(二十)分数
    《Two Dozen Short Lessons in Haskell》学习(十八) 交互式键盘输入和屏幕输出
    Exercise: A Routine Day
    读书笔记2013第6本:《棋与人生》(二)
    读书笔记2013第8本:《超级快速阅读》
    TC的房子
    [转贴]Windows批处理调用程序后如何自动退出
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15113465.html
Copyright © 2011-2022 走看看