HDU 1536 & 1944

http://acm.hdu.edu.cn/showproblem.php?pid=1536

http://acm.hdu.edu.cn/showproblem.php?pid=1944

一样的题

题意:先给一个集合,代表可能发生的转移。然后m个询问,可以理解为每次给l堆石子,每堆有hi个,问博弈策略

直接用sg定理,非常简单,转移给的清清楚楚,照着写就行,递推或者记忆化搜索都行。

这题的时间卡的紧,开始死活过不了,看别人代码把vis数组开成100就过了(原来开的1w),深感此题有问题,sg的值最大应该1w才对(或者我想错了欢迎指出?)

AC 代码

#include <iostream>

#include <cstdio>

#include <cstring>

#include <set>

#include <algorithm>



using namespace std;



int sg[10005], vis[105], s[105], k;



void getSG() {

    sg[0] = 0;

    for(int j = 1; j <= 10000; j++) {

        memset(vis, 0, sizeof(vis));

        for(int i = 0; i < k; i++) {

            if(s[i] <= j) vis[sg[j-s[i]]] = 1;

        }

        for(int i = 0; ; i++) {

            if(!vis[i]) {

                sg[j] = i;

                break;

            }

        }

    }

}



int main() {

    while(~scanf("%d", &k), k) {

        for(int i = 0; i < k; i++)

            scanf("%d", &s[i]);

        getSG();

        int m;

        scanf("%d", &m);

        while(m--) {

            int l;

            scanf("%d", &l);

            int ans = 0;

            while(l--) {

                int h;

                scanf("%d", &h);

                ans ^= sg[h];

            }

            if(!ans) putchar('L');

            else putchar('W');

        }

        putchar('\n');

    }

    return 0;

} 
View Code
#include <iostream>

#include <cstdio>

#include <cstring>

#include <set>

#include <algorithm>



using namespace std;



int sg[10005], vis[105], s[105], k;



int getSG(int x) {

    if(sg[x] != -1) return sg[x]; 

    memset(vis, 0, sizeof(vis));

    for(int i = 0; i < k; i++) {

        if(s[i] <= x) {

            getSG(x-s[i]);

            vis[sg[x-s[i]]] = 1;

        }

    }

    for(int i = 0; ; i++) {

        if(!vis[i]) return sg[x] = i;

    }

}



int main() {

    while(~scanf("%d", &k), k) {

        for(int i = 0; i < k; i++)

            scanf("%d", &s[i]);

        int m;

        scanf("%d", &m);

        memset(sg, -1, sizeof(sg));

        sg[0] = 0;

        for(int i = 0; i <= 10000; i++)

            getSG(i);

        while(m--) {

            int l;

            scanf("%d", &l);

            int ans = 0;

            while(l--) {

                int h;

                scanf("%d", &h);

                ans ^= sg[h];

            }

            if(!ans) putchar('L');

            else putchar('W');

        }

        putchar('\n');

    }

    return 0;

} 
View Code

超时代码(但感觉非常正确,不知道被卡在哪里)

#include <iostream>

#include <cstdio>

#include <cstring>

#include <set>

#include <algorithm>



using namespace std;



int sg[10005], s[105], k;



void getSG() {

    sg[0] = 0;

    for(int j = 1; j <= 10000; j++) {

        set <int> S;

        for(int i = 0; i < k; i++) {

            if(s[i] <= j) S.insert(sg[j-s[i]]);

        }

        int g = 0;

        while(S.count(g)) g++;

        sg[j] = g; 

    }

}



int main() {

    while(~scanf("%d", &k), k) {

        for(int i = 0; i < k; i++)

            scanf("%d", &s[i]);

        getSG();

        int m;

        scanf("%d", &m);

        while(m--) {

            int l;

            scanf("%d", &l);

            int ans = 0;

            while(l--) {

                int h;

                scanf("%d", &h);

                ans ^= sg[h];

            }

            if(!ans) putchar('L');

            else putchar('W');

        }

        putchar('\n');

    }

    return 0;

} 
View Code
#include <iostream>

#include <cstdio>

#include <cstring>

#include <set>

#include <algorithm>



using namespace std;



int sg[10005], s[105], k;



int getSG(int x) {

    if(sg[x] != -1) return sg[x]; 

    set <int> S;

    for(int i = 0; i < k; i++) {

        if(s[i] <= x) {

            S.insert(getSG(x-s[i]));

        }

    }

    int g = 0;

    while(S.count(g)) g++;

    return sg[x] = g;

}



int main() {

    while(~scanf("%d", &k), k) {

        for(int i = 0; i < k; i++)

            scanf("%d", &s[i]);

        int m;

        scanf("%d", &m);

        memset(sg, -1, sizeof(sg));

        sg[0] = 0;

        for(int i = 0; i <= 10000; i++)

            getSG(i);

        while(m--) {

            int l;

            scanf("%d", &l);

            int ans = 0;

            while(l--) {

                int h;

                scanf("%d", &h);

                ans ^= sg[h];

            }

            if(!ans) putchar('L');

            else putchar('W');

        }

        putchar('\n');

    }

    return 0;

} 
View Code

 

你可能感兴趣的:(HDU)