Uva--10404(动规,博弈)
2014-08-02 16:13:18
Problem B: Bachet's Game
Bachet's game is probably known to all but probably not by this name. Initially there are n stones on the table. There are two players Stan and Ollie, who move alternately. Stan always starts. The legal moves consist in removing at least one but not more than k stones from the table. The winner is the one to take the last stone.
Here we consider a variation of this game. The number of stones that can be removed in a single move must be a member of a certain set ofm numbers. Among the m numbers there is always 1 and thus the game never stalls.
Input
The input consists of a number of lines. Each line describes one game by a sequence of positive numbers. The first number is n <= 1000000 the number of stones on the table; the second number is m <= 10 giving the number of numbers that follow; the last m numbers on the line specify how many stones can be removed from the table in a single move.
Input
For each line of input, output one line saying either Stan wins or Ollie wins assuming that both of them play perfectly.
Sample input
20 3 1 3 8 21 3 1 3 8 22 3 1 3 8 23 3 1 3 8 1000000 10 1 23 38 11 7 5 4 8 3 13 999996 10 1 23 38 11 7 5 4 8 3 13
Output for sample input
Stan wins Stan wins Ollie wins Stan wins Stan wins Ollie wins
思路:很有意思的一道题目,结合了博弈的知识。首先dp[k]表示还剩k个石头的状态,dp[k] == 1表示必胜态,dp[k] == 0表示必败态。
由两条博弈准则:
1:当前状态为必胜态,当且仅当他的后继状态中至少有一个必败态。
2:当前状态为必败态,当且仅当他的后继状态全部都为必胜态。
而这题只用到了 1 准则,dp[0]必为必败态(因为没有剩余的石头可取了),所以可以从dp[0]开始往起点dp[n]推即可。
1 /************************************************************************* 2 > File Name: f.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Wed 30 Jul 2014 04:10:19 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 int n,m,v[15]; 17 int dp[1000005]; 18 19 int main(){ 20 while(scanf("%d%d",&n,&m) == 2){ 21 memset(dp,-1,sizeof(dp)); 22 for(int i = 0; i < m; ++i) 23 scanf("%d",&v[i]); 24 for(int i = 0; i <= n; ++i){ 25 dp[i] = 0; 26 for(int j = 0; j < m; ++j){ 27 if(i - v[j] >= 0 && !dp[i - v[j]]){ 28 dp[i] = 1; 29 break; 30 } 31 } 32 33 } 34 if(dp[n]) 35 printf("Stan wins\n"); 36 else 37 printf("Ollie wins\n"); 38 } 39 return 0; 40 }