取石子游戏的变体。
题意:有m堆石子,事先给定一个集合S,每次只能从一堆中取石子,且取的石子个数必须是S中的数。没有石子可取或者不能按规则取石子即为输。
给定初始情况,判断最开始的局面是必败L,还是必胜W局面。
这题如果知道SG函数,就很好解了。由sg的基础知识可知,某一局面的sg值为0则对应P局面,反之对应N局面,所以把最终局面的sg值求出来就可以了。
这里在用到一个定理:
设gi为子游戏Gi的SG函数,那么组合游戏G的SG函数为:g(x1,x2,x3,...xn) = g1(x1) xorg2(x2) xor... xorgn(xn)
先考虑只有一堆的情况,在把各堆的sg值异或就可以了。这是一个求一维sg函数的值,求sg时用记忆化搜索就行。
View Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define see(x) cout<<#x<<":"<<x<<endl;
using namespace std;
int s[105], k;
int sg[10005];
int dfs(int x){
if(sg[x]!=-1) return sg[x];
int i, f=0;
bool vis[105] = {0};
for(i=0;i<k;i++){
if(x-s[i]>=0){
dfs(x-s[i]);
vis[sg[x-s[i]]] = true;
}
}
for(i=0;i<105;i++){
if(vis[i]==false){
f = i;
break;
}
}
return sg[x] = f;
}
int main(){
int m, n, i, j, l, t, ans;
while(~scanf("%d",&k)&&k){
for(i=0;i<k;i++){
scanf("%d",&s[i]);
}
memset(sg,-1,sizeof(sg));
sg[0] = 0;
scanf("%d",&t);
while(t--){
ans = 0;
scanf("%d",&l);
for(i=0;i<l;i++){
scanf("%d",&j);
ans ^= dfs(j);
}
//see(ans)
if(ans){
cout<<"W";
}
else{
cout<<"L";
}
}
cout<<endl;
}
return 0;
}
唉,搜索能力还是太弱了……
取石子游戏的变体。题意:有m堆石子,事先给定一个集合S,每次只能从一堆中取石子,且取的石子个数必须是S中的数。没有石子可取或者不能按规则取石子即为输。给定初始情况,判断最开始的局面是必败L,还是必胜W局面。这题如果知道SG函数,就很好解了。由sg的基础知识可知,某一局面的sg值为0则对应P局面,反之对应N局面,所以把最终局面的sg值求出来就可以了。这里在用到一个定理: 设gi为子游戏Gi的SG函数,那么组合游戏G的SG函数为:g(x1,x2,x3,...xn) = g1(x1) xorg2(x2) xor... xorgn(xn)先考虑只有一堆的情况,在把各堆的sg值异或就可以了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define see(x) cout<<#x<<":"<<x<<endl;
using namespace std;
int s[105], k;
int sg[10005];
int dfs(int x){ //记忆化搜索确定SG值
if(sg[x]!=-1) return sg[x];
int i, f=0;
bool vis[105] = {0};
for(i=0;i<k;i++){
if(x-s[i]>=0){
dfs(x-s[i]);
vis[sg[x-s[i]]] = true;
}
}
for(i=0;i<105;i++){
if(vis[i]==false){
f = i;
break;
}
}
return sg[x] = f;
}
int main(){
int m, n, i, j, l, t, ans;
while(~scanf("%d",&k)&&k){
for(i=0;i<k;i++){
scanf("%d",&s[i]);
}
memset(sg,-1,sizeof(sg));
sg[0] = 0;
scanf("%d",&t);
while(t--){
ans = 0;
scanf("%d",&l);
for(i=0;i<l;i++){
scanf("%d",&j);
ans ^= dfs(j);
}
if(ans){
cout<<"W";
}
else{
cout<<"L";
}
}
cout<<endl;
}
return 0;
}