POJ 1143 Number Game 动态规划+位操作

POJ 1143 Number Game 动态规划+位操作

题目大意:
两个人玩游戏。轮流取数字,范围在1~20之间。
规定:
1. 取过的数字不能再取。
2. 取过的数字的倍数不能再取。
3. 任意个(2)的和不能再取。

当某个人发现没有数字可取时,他就输了。
给出一个“残局”。问,我现在应该怎么取,才能保证胜利。

思路:
其实这个也不是很难的博弈问题。只是搜索就可以解决了。要用位来表示当前剩余数字的状态,
方便保存动态规划的结果。


#include  < stdio.h >

#define  N 20

char  dp[ 2 ][ 1   <<  (N  +   1 )];

__inline 
int  use( int  visited,  int  idx)
{
    
int i;

    
for (i = 0; i + idx <= N; i++{
        
if (visited & (1 << i))
            visited 
|= 1 << (i + idx);
    }

    
return visited;
}


int  dfs( int  my_step,  int  visited)
{
    
int i, r;

    
if (visited == (1 << (N + 1)) - 1
        
return !my_step;
    
    r 
= dp[my_step][visited];
    
if (r)
        
return r - 1;

    
for (i = 2; i <= N; i++{
        
if (visited & (1 << i))
            
continue;
        r 
= dfs(!my_step, use(visited, i));
        
if (my_step && r)
            
return 1;
        
if (!my_step && !r)
            
return 0;
    }


    dp[my_step][visited] 
= !my_step + 1;
    
return !my_step;
}


int  main()
{
    
int n, v, i, arr[24], cnt, t;

    freopen(
"e:\\test\\in.txt""r", stdin);

    
for (t = 1; scanf("%d"&n), n; t++{
        v 
= ((1 << (N + 1)) - 1& ~2;
        
while (n--{
            scanf(
"%d"&i);
            v 
&= ~(1 << i);
        }

        cnt 
= 0;
        
for (i = 2; i <= N; i++{
            
if (v & (1 << i))
                
continue;
            
if (dfs(0, use(v, i)))
                arr[cnt
++= i;
        }

        printf(
"Test Case #%d\n", t);
        
if (cnt) {
            printf(
"The winning moves are:");
            
for (i = 0; i < cnt; i++
                printf(
" %d", arr[i]);
            printf(
"\n");
        }
 else 
            printf(
"There's no winning move.\n");
        printf(
"\n");
    }


    
return 0;
}


你可能感兴趣的:(POJ 1143 Number Game 动态规划+位操作)