我最近学习了竞争性编程的位操作概念,所以我对这个概念很新,我还阅读了很多有关 Bit-Masking + Dynamic Programming 的教程在Hackerearth,CodeChef等等。
我还解决了Codechef上的一些问题,包括这个问题problem 在我遇到一些问题后,我对Bitmasks有一些疑问。
我解决的问题主要集中在操作子集但我想知道如何使用位掩码处理排列,即当我必须处理一个状态时需要设置掩码中的所有位。
例如:如果我们必须找到可以通过排列给定数字A的所有数字而形成的数字,这些数字可被给定数字B整除,其中(A,B <= 10 ** 6)如何使用位掩码完成。(我希望可以用bitmask + dp完成)
如果A = 514,B = 2 问题希望答案是
514
154
哪些都可以被2整除。
所以答案是2。 凭借我的知识:514和154表示相同的掩码 111 ,其中所有位都 set 那么如何在这里使用掩码相同的位掩码用于两个或更多答案!(我希望你理解这一点)。
而且因为我们可以使用那么多的数字排列来分配n值为n!* n的内存是不可能的,因为我们可以使用仅需要的位掩码来完成这个问题(2 ** n )* n空间(如果我没错)。
那么如何迭代地解决上述问题呢? /或者我可能理解的任何DP状态方程,我无法理解我读过的一些类似问题的递归方法。
我也试着考虑类似的问题TSHIRTS,但我无法理解递归背后的逻辑。
答案 0 :(得分:0)
你实际上并不需要这个DP但你可以很好地使用位操作:)因为A&lt; = 10 ^ 6这意味着A有7个数字;所以你只需要检查7! = 5040州。
const int A = 514;
const int B = 2;
vector <int> v; //contains digits of A (e.g. 5, 1, 4) this can be done before the recursive function in a while loop.
int rec(int mask, int current_number){
if(mask == (1 << v.size()) - 1){ //no digit left to pick
if(current_number % B == 0) return 1;
else return 0;
}
int ret = 0;
for(int i = 0; i < v.size(); i++){
if(mask & (1 << i)) continue; //this is already picked
ret += rec(mask | (1 << i), current_number * 10 + v[i]);
}
return ret;
}
请注意,我在这里没有使用DP的原因是,即使掩码相同,当前数字也可能不同;所以你实际上不能说情况已经重演了。除非你记住掩码 AND current_number,它需要更多的空间。