甲乙两个人用一个英语单词玩游戏。两个人轮流进行,每个人每次从中删掉任意一个字母,如果剩余的字母序列是严格单调递增的(按字典序a < b < c <....<z),则这个人胜利。两个人都足够聪明(即如果有赢的方案,都不会选输的方案 ),甲先开始,问他能赢么?
输入: 一连串英文小写字母,长度不超过15,保证最开始的状态不是一个严格单增的序列。
输出:1表示甲可以赢,0表示甲不能赢。
例如: 输入 bad, 则甲可以删掉b或者a,剩余的是ad或者bd,他就赢了,输出1。
又如: 输入 aaa, 则甲只能删掉1个a,乙删掉一个a,剩余1个a,乙获胜,输出0。
函数头部:
C:int who (const char * word);
C++:int who (string word);
Java:public static int who(String in);
C# :public static int who(string word);
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 单词博弈
{
class Program
{
static String str;
static int length;
static int[] mask;
static int[] permutationCache;
static int[] stateCache;
/// <summary>
/// 判断是否为递增
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
private static int checkPermutation(int state)
{
//如果这个数组里本身有值直接取出返回
if (permutationCache[state] != -1)
{
return permutationCache[state];
}
char previous = char.MinValue;
char current;
int result = 1;
for (int i = 0; i < length; ++i)
{
//循环取出每一位忽略掉0 此时mark是1000..这种形式
if ((mask[i] & state) == 0)
{
continue;
}
//取出当前的字符
current = str[i];
if (current <= previous)
{
result = 0;
break;
}
previous = current;
}
//将这个数的值保存在数组里
return permutationCache[state] = result;
}
/// <summary>
/// 判断谁赢
/// </summary>
/// <param name="state">数对应的位图</param>
/// <returns></returns>
private static int checkState(int state)
{
//如果状态表中有值直接取出,这里这样用是可以的因为每个对应一个1111去掉之后就是0111,1011,1001,0001每个都不同
if (stateCache[state] != -1)
{
return stateCache[state];
}
int result = 0;
int next;
for (int i = 0; i < length; ++i)
{
//忽略掉为0的
if ((mask[i] & state) == 0)
{
continue;
}
next = state & ~mask[i];
if (checkPermutation(next) == 1 || checkState(next) == 0)
{
result = 1;
break;
}
}
return stateCache[state] = result;
}
public static int who(String word)
{
str = word;
length = word.Length;
permutationCache = new int[1 << length];
for (int i = 0; i < permutationCache.Length; i++)
{
permutationCache[i] = -1;
}
//状态对应表每次使用who都要重新创建
stateCache = new int[1 << length];
for (int i = 0; i < permutationCache.Length; i++)
{
stateCache[i] = -1;
}
mask = new int[16];
for (int i = 0; i < 16; ++i)
{
mask[i] = 1 << i;
}
return checkState((1 << length) - 1);
}
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
//string str = "onmlkjihgfedcba";
//Console.WriteLine(str.Length);
//for (int i = 0; i < 10; i++)
//{
// Console.WriteLine(who(str));
//}
string str = "cab";
string str2 = "cba";
Console.WriteLine(who(str));
Console.WriteLine(who(str2));
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed);
Console.ReadKey();
}
}
}