1. 程式人生 > >50 博弈(逆著順序求sg值)

50 博弈(逆著順序求sg值)

There are three piles of beans. TT and DD pick any number of beans from any pile or the same number from any two piles by turns. Who get the last bean will win. TT and DD are very clever.

Input

Each test case contains of a single line containing 3 integers a b c, indicating the numbers of beans of these piles. It is assumed that 0 <= a

,b,c <= 300 and a + b + c > 0.

Output

For each test case, output 1 if TT will win, ouput 0 if DD will win.

Sample Input

1 0 0
1 1 1
2 3 6

Sample Output

1
0
0

這道題目的意思很簡單就是有三堆石子,一次操作可以拿一堆石子中的任意的石子數目,也可以任意選擇兩堆石子,拿走相同數量的石子,問一下先手是否是有必勝的策略如果有的話就輸出1,否則的話就輸出0;

這道題目如果是採用原始的求算sg的方法的話,就是對於當前的狀態求算他的後繼狀態的話會發現,時間複雜度是會超時的,因為我們每次都需要初始化一遍標記陣列,但是我們會發現這道題目有一個特點就是隻需要判斷當前是否是必勝狀態就可以了,不需要一定要知道這個狀態的sg值,只是判斷是否是必勝的狀態,怎麼判斷呢;

我們可以這麼想如果當前的狀態是必輸的狀態的話,那麼通過一次操作可以到達它的狀態不就是必勝狀態了嗎,這樣的的話我們就可以省掉標記直接把後繼狀態是必輸的狀態標記為必勝就可以了,其實這道題目跟前面部落格的一道題目是很相似的就是對多堆石子來操作;

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int Max = 305;
int sg[Max][Max][Max];

void pri(){
    for(int a=0;a<=300;a++){
       for(int b=0;b<=300;b++){
         for(int c=0;c<=300;c++){
             if(sg[a][b][c]==0){
                for(int i=1;i+a<=300;i++)            sg[i+a][b][c]=1;
                for(int i=1;i+b<=300;i++)            sg[a][i+b][c]=1;
                for(int i=1;i+c<=300;i++)            sg[a][b][i+c]=1;
                for(int i=1;i+a<=300&&i+b<=300;i++)  sg[i+a][i+b][c]=1;
                for(int i=1;i+a<=300&&i+c<=300;i++)  sg[i+a][b][i+c]=1;
                for(int i=1;b+i<=300&&i+c<=300;i++)  sg[a][b+i][i+c]=1;
             }
           }
         }
       }
}
int main(){

   pri();
   int a,b,c;
   while(scanf("%d %d %d",&a,&b,&c)!=EOF){
    if(1){
        printf("1\n");
    }
    else {
        printf("0\n");
    }
   }
   return 0;
}