P2953 [USACO09OPEN]牛的数字游戏Cow Digit Game

题目描述

Bessie is playing a number game against Farmer John, and she wants you to help her achieve victory.

Game i starts with an integer N_i (1 <= N_i <= 1,000,000). Bessie goes first, and then the two players alternate turns. On each turn, a player can subtract either the largest digit or the smallest non-zero digit from the current number to obtain a new number. For example, from 3014 we may subtract either 1 or 4 to obtain either 3013 or 3010, respectively. The game continues until the number becomes 0, at which point the last player to have taken a turn is the winner.

Bessie and FJ play G (1 <= G <= 100) games. Determine, for each game, whether Bessie or FJ will win, assuming that both play perfectly (that is, on each turn, if the current player has a move that will guarantee his or her win, he or she will take it).

Consider a sample game where N_i = 13. Bessie goes first and takes 3, leaving 10. FJ is forced to take 1, leaving 9. Bessie takes the remainder and wins the game.

贝茜和约翰在玩一个数字游戏.贝茜需要你帮助她.

游戏一共进行了G(1≤G≤100)场.第i场游戏开始于一个正整数Ni(l≤Ni≤1,000,000).游

戏规则是这样的:双方轮流操作,将当前的数字减去一个数,这个数可以是当前数字的最大数码,也可以是最小的非0数码.比如当前的数是3014,操作者可以减去1变成3013,也可以减去4变成3010.若干次操作之后,这个数字会变成0.这时候不能再操作的一方为输家. 贝茜总是先开始操作.如果贝茜和约翰都足够聪明,执行最好的策略.请你计算最后的赢家.

比如,一场游戏开始于13.贝茜将13减去3变成10.约翰只能将10减去1变成9.贝茜再将9减去9变成0.最后贝茜赢.

输入格式

* Line 1: A single integer: G

* Lines 2..G+1: Line i+1 contains the single integer: N_i

输出格式

* Lines 1..G: Line i contains 'YES' if Bessie can win game i, and 'NO' otherwise.

输入输出样例

输入 #1
2 

9 

10 

输出 #1
YES 

NO 

说明/提示

For the first game, Bessie simply takes the number 9 and wins. For the second game, Bessie must take 1 (since she cannot take 0), and then FJ can win by taking 9.

思路

每种状态可以转移出两个新状态。博弈论的结论:

当某种状态的后继状态都是必败状态时,该状态为必胜状态;

当某种状态的后继状态有一种是必胜状态时,该状态为必败状态。

所以先将0标记为必败,1-9标记为必胜(显然),从10-1000000遍历一遍,用f数组存必败或必胜,然后输出就可以了。在求f[i]的时候只会用到f[i-max/min],而max/min必然大于0,所以顺序遍历即可。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=1000010;

int q,n;
int f[N];

int minn(int a) {
	int num;
	num=20;
	while(a) {
		if(a%10)
			num=min(num,a%10);
		a/=10;
	}
	return num;
}

int maxx(int a) {
	int num;
	num=-10;
	while(a) {
		if(a%10)
			num=max(num,a%10);
		a/=10;
	}
	return num;
}

int main () {
	memset(f,false,sizeof(f));
	for(int i=1; i<=9; i++)
		f[i]=true;
	for(int i=11; i<=N; i++)
		if(f[i-minn(i)]&&f[i-maxx(i)])
			f[i]=false;
		else
			f[i]=true;
	scanf("%d",&n);
	for(int i=1; i<=n; i++) {
		scanf("%d",&q);
		if(f[q]==false)
			printf("NO\n");
		else
			printf("YES\n");
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/mysh/p/11333427.html