这是编程竞赛中的problem 在那里我“发现”如何通过双人游戏进入各州。
问题是:在两个玩家A和B之间玩另一种游戏,其中A总是首先开始并从给定矩阵中选择一些字母并从给定字典中制作单词。然后丢弃这些字母。 下一位玩家从左边选择字母。最后一个不能说话的人输了。每次发挥最佳。
来自editorial 我在这里引用
To iterate over all non-empty subsets of the given
set when they represented using bitmasks:
submask = mask
while submask > 0
// do the job with the submask
submask = (submask - 1) AND mask
在我看到的其中一个解决方案中
int solve(int state)
{
if(dp[state]!=-1)
return(dp[state]);
int res=1;
int nstate=state;
while(1)
{
if(valid[nstate])
res=solve(state&(~nstate));
if(res==0)
break;
nstate=((nstate-1)&state);
if(nstate==0)
break;
}
if(res==0)
dp[state]=1;
else
dp[state]=0;
return(dp[state]);
}
此代码的另一个AND与〜。
我实际上无法理解这里的“状态”是什么,以及这个AND如何通过所有状态?请解释一下。
答案 0 :(得分:2)
状态是剩余字母的集合。
我们用1代替我们仍然拥有的字母,以及用0代替的字母。
这导致二进制数,它是变量掩码中保存的数字。
例如,假设我们在游戏开始时有字母ABCDEFGH,并且在某个时刻我们只剩下字母B和D.
数字0x50表示当前状态:
ABCDEFGH at start
-B-D---- at current point in game
01010000 replace with 1's for letters we still have
0x50 treat as a binary number
两种解决方案都使用位旋转nstate=((nstate-1)&state)
。
如果从nstate = state开始,此代码将生成该状态的所有子集。
这是什么意思?好吧,假设我们的状态是当前字母B和D.此状态的所有非空子集都是{B,D},{B},{D}。
这些将由二进制数01010000,01000000,00010000表示。
我们可以看到这些确实是通过执行以下Python代码生成的:
state=0b01010000
nstate=state
while nstate:
print bin(nstate)
nstate=(nstate-1)&state
提供输出:
0b01010000
0b01000000
0b00010000
为什么这样做?
粗略地说,代码使用nstate = nstate-1
来计算所有可能的二进制数,而& state
会跳过我们不关心的位数发生变化的部分(通过立即将它们设置为零,而不是等待它们倒数到零)。