我们遇到了一个问题,我已将其简化为以下内容: 您将获得一个包含所有值的二进制数(例如11111)和一组长度相同的二进制数(00101,10000,01100,00100,11100)。 有两名球员A& B.在每个转弯处,玩家可以从主二进制数(11111)中减去任何一个较小的数字,使得2的二进制AND是较小的数字。然后下一个玩家可以从结果中减去,依此类推。不能再减去的玩家输了。 例如
A B
11111 11010 // Now A cannot subtract
-00101 -10000 // anymore in the next turn.
------- ------ // So B wins the game.
11010 01010
------- ------
如果两位球员都发挥出最佳效果(为他们的胜利做出最佳选择),我必须找出哪位球员在给定的二进制数组合中获胜。
我尝试过O(n ^ 2)方法,但有更快的方法吗?
编辑: O(n ^ 2):其中n是状态数。对于长度为6(111111)的二进制数,可能存在2 ^ 6个状态。所以我的复杂性是O((2 ^ 6)^ 2)。
编辑: 我的代码生成所有可能的状态:
void makeAllStates() /* Bottom Up Approach. Starting from 00000 and going to 11111 */
{
// bool states[i] : True if state[i] is a winning position.
// bool isWord[i] : True if the given state matches a smaller number. (eg. If the main number has been reduced to 10110 and there is a smaller number 10110, then isWord[i] is true.
// bool visited[i] : True If the given state has been visited
// int statecount : Total number of states
int temp;
for(int xx=1;xx<stateCount;xx++)
{
for(int yy=1;yy<stateCount;yy++)
{
if(xx&yy)
continue;
if(!(isWord[xx] || isWord[yy]))
continue;
if(!visited[yy])
continue;
temp = xx^yy;
if(isWord[temp])
continue;
if(states[temp])
continue;
if(isWord[xx] && isWord[yy])
states[temp] = false;
else
{
if(isWord[xx])
states[temp] = !states[yy];
else
states[temp] = !states[xx];
}
visited[temp] = true;
if(temp == stateCount-1 && states[temp])
{
return;
}
}
}
}
答案 0 :(得分:3)
我不知道它是否会对你有帮助(你讲过O(n ^ 2)方法,但没有说出N的意思)。尝试通用的公正游戏方法(Sprague-Grundy理论):
请注意,您可以递归地考虑每个游戏位置,并且您将考虑位置x一次(在计算g(x)时),因此该算法线性的可能位置数。线性的位置之间可能的转弯次数,即O(N * K),其中N是状态数,K是较小数字组的大小(您可以在游戏中转弯)
如果g(START_POSITION)= 0,则开始位置是失去位置,并且第一个玩家失去(每个回合导致获胜位置)。如果g(START_POSITION)&gt; 0然后开始位置是获胜位置(存在转向位置x使得g(x)= 0),所以第一个玩家获胜。
抱歉英语不好,希望能有所帮助
答案 1 :(得分:0)
根据K.Bulatov的输入,这是最终的代码,在最坏的情况下时间复杂度为O(n ^ 2)。修剪后,呼叫次数在很大程度上减少了。 主要功能如下:
//state : The state for which grundy number is being queried.
//visited[i] : If the grundy number of the state has already been calculated.
//wordStates[] : an array with all the smaller numbers stored.
//mex() : "minimal excludant" - the smallest non-negative integer not in array
int grundyNum(int state)
{
if(visited[state])
return grundy[state];
int grundArr[wordStates.size()];
int loc =0;
visited[state] = true;
for(int xx =0;xx<wordStates.size();xx++)
{
if((state&wordStates[xx]) == wordStates[xx])
{
grundArr[loc] = grundyNum(state^wordStates[xx]);
loc++;
}
}
grundy[state] = mex(grundArr,loc);
return grundy[state];
}
只需使用以下功能调用该功能即可获胜:
result = grundy(1111111);
winner = result==0?"B":"A";