题意:给n个数的集合s, 再给m 组数据,每组表示 k 堆石子,每次可以取的个数只能是集合s中的数量。问先手胜还是输?
简单的SG 函数 求知 ,无规律,直接DP 求得所有解即可 。
在求值时 有两种方式 。 第一种先求出所有解。把所有的可能的数都求出来。
还有一种 是 递归 求解。 只是在用到时, 求解。 依次求其子状态的值, 最终求出当前一个值得解,但是其子状态也已经求出,在用到时,直接返回,类似记忆化的形式。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
const double EPS = 1e-8;
#define LL long long
#define pb push_back
const int maxn = 10001;
int f[maxn];
int s[110];
int mark[110];
int tot;
int n;
void init(){
for(int i=0;i<maxn;i++){
f[i] = 1;
}
f[0]=0;
for(int i=1;i<=maxn;i++){
for(int j=0;j<=n;j++){
mark[j] = 0;
}
for(int j=1;j<=n;j++){
int k = i-s[j];
if(k<0)break;
if(f[k]<=n)
mark[f[k]] = 1;
}
//sort(mark+1,mark+tot+1);
int ans = 0;
for(int j =0;j<=n;j++){
if(!mark[j]){
ans = j ;
break;
}
}
f[i] =ans;
}
}
int main(){
while(~scanf("%d",&n),n){
for(int i=1;i<=n;i++){
scanf("%d",&s[i]);
}
sort(s+1,s+n+1);
init();
int m;
cin >> m;
while(m--){
int t ;
scanf("%d",&t);
int ans = 0;
for(int i =1;i<=t;i++){
int a;
scanf("%d",&a);
ans ^= f[a];
}
if(ans){
printf("W");
}else{
printf("L");
}
if(m==0)puts("");
}
}
return 0;
}
第二种。。待更新。