hdu 5754 博弈递推 dfs记忆优化

来源:互联网 发布:qq清除数据后怎么恢复 编辑:程序博客网 时间:2024/05/15 23:46

分析
根据博弈递推的原则:
-必败态只能转移到必胜态。
-必胜态一定可以转移到必败态。
dp[i][j][op]为在棋盘中(i,j)位置,棋子为op时的胜败状态,根据其子状态递推即可。
这里注意车只有对角线是必败很显然。
对于马,如果它只能走到必胜态和平态,那么它就宁愿走到平态,这比输了好。
皇后的时候转移有可能是O(n)的会复杂度过高,所以要记录哪些行哪些列哪些对角线有必败态了。
所在对角线不好根据坐标直接求到,所以用pre()预处理出来。
心得:
dp复杂度估算是,要用最坏转移复杂度,并且想办法降低dp维度或者转移复杂度。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define pr(x) cout << #x << ": " << x << "  " #define pl(x) cout << #x << ": " << x << endl;struct jibancanyang{    int dp[1009][1003][5], n, m, p;    bool row[1009], col[1009], dia[3009];    int diagonal[1009][1009];    void pre() {        int cnt = 0;        for (int i = 1; i <= 1000; i++) {            for (int j = 1; j <= 1000; j++) {                if(i - 1 > 0 && j - 1 > 0) diagonal[i][j] = diagonal[i - 1][j - 1];                else diagonal[i][j] = cnt++;            }        }    }    int dfs(int x, int y, int op) {        int n = 1000, m = 1000;        //if (op == 4) pr(x), pr(y), pl(dp[x][y][4]);        if (dp[x][y][op]) return dp[x][y][op];        if (x == 1000 && y == 1000) return dp[x][y][op] = -1;        if (op == 1) {            bool have = false, havefail = false;            int a = x + 1, b = y;            if (a <= n && b <= m) {                int temp = dfs(a, b, op);                if (temp != 100) have = true;                if (temp == -1) havefail = true;            }            a = x + 1, b = y + 1;            if (a <= n && b <= m) {                int temp = dfs(a, b, op);                if (temp != 100) have = true;                if (temp == -1) havefail = true;            }            a = x, b = y + 1;            if (a <= n && b <= m) {                int temp = dfs(a, b, op);                if (temp != 100) have = true;                if (temp == -1) havefail = true;            }            if (have) {                return dp[x][y][op] = havefail ? 1 : -1;            } else return dp[x][y][op] = 100;        }        if (op == 2) {            if (x == y) return dp[x][y][op] = -1;            else return dp[x][y][op] = 1;        }        if (op == 3) {            bool have = false, havefail = false;            bool G = false;            int a = x + 1, b = y + 2;            if (a <= n && b <= m) {                int temp = dfs(a, b, op);                if (temp != 100) have = true;                else G = true;                if (temp == -1) havefail = true;            }            a = x + 2, b = y + 1;            if (a <= n && b <= m) {                int temp = dfs(a, b, op);                if (temp != 100) have = true;                else G = true;                if (temp == -1) havefail = true;            }            if (have) {                if (havefail) dp[x][y][op] = 1;                else {                    if (G) dp[x][y][op] = 100;                    else dp[x][y][op] = -1;                }                return dp[x][y][op];            } else return dp[x][y][op] = 100;        }        if (op == 4) {            if (row[x] || col[y] || dia[diagonal[x][y]]) return dp[x][y][op] = 1;            row[x] = true, col[y] = true, dia[diagonal[x][y]] = true;            return dp[x][y][op] = -1;        }        return 0;    }    void bug() {       for (int p = 1; p <= 4; p++) {            cout << "P :" << p << endl;        for (int i = 1; i <= 1000; i++) {            for (int j = 1; j <= 1000; j++) {                    int k = dfs(i, j, p);                    /*                    if (k == 10) printf("    ");                    else                     printf("%3d", (k == 100 ? 2 : (k == 1 ? 1 : 0)));                    */            }            //cout << endl;        }         //cout << endl;       }    }    void fun() {        int T;        scanf("%d", &T);        memset(dp, 0, sizeof(dp));        memset(row, 0, sizeof(row));        memset(col, 0, sizeof(col));        memset(dia, 0, sizeof(dia));        pre();        row[1000] = true, col[1000] = true, dia[diagonal[1000][1000]] = true;        for (int i = 1000; i > 0; i--) {            for (int j = 1000; j > 0; j--) {                if ((i == 1000 && j == 1000) || dp[i][j][4]) continue;                if (row[i] || row[j] || dia[diagonal[i][j]]) dp[i][j][4] = 1;                else {                    row[i] = true, row[j] = true, dia[diagonal[i][j]] = true;                    dp[i][j][4] = -1;                    dp[j][i][4] = -1;                }            }        }        while (T--){            scanf("%d%d%d", &p, &n, &m);            int ans;            ans = dfs(1000 - n + 1, 1000 - m + 1, p);            if (ans == 100) puts("D");            else if (ans == 1) puts("B");            else puts("G");        }    }}ac;int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);    //freopen("out.txt", "w", stdout);#endif    ac.fun();    //ac.bug();    return 0;}
0 0
原创粉丝点击