P2540 斗地主 加强版/P2668 斗地主 题解
Starrykiller · · 题解
(可能)更好的阅读体验?
和 @luchuhan 共同想出来的做法~
关于如何搜索和怎么强剪枝其他题解已经说得很清楚了(如果不清楚请参阅其他题解)。那么这里提供另外一个优化的方法(似乎题解里面没有人这么写)
在写 dfs 的时候,我们会加上这样一条剪枝:
void dfs(int step, int cnt) { // 打了 step 手牌,用了 cnt 张
if (step>=ans) return;
// do something
}
这样剪枝的正确性是显然的。但是这样剪枝针对的情况只有一种:
我们不妨记
显然一个状态就是这样的一个集合:
如果简单地用一个
其中 unsigned long long 的自然溢出(map<unsigned long long, int> 或者 对素数取模+数组 来进行记录。
其实用结构体之类的东西记录下状态也可以。
于是就能得到极大的优化。
// 这里把牌映射到了[13,17]
unsigned long long hsh() {
unsigned long long res=0;
for (int i=3; i<=17; ++i) {
res=res*p+card[i];
}
return res;
}
map<unsigned long long, int> m;
void dfs(int step, int cnt) { // 打了 step 手牌,用了 cnt 张
if (cnt>=n || step>=ans) {
ans=min(ans, step);
return;
}
auto h=hsh();
if (m.find(h)!=m.end() && step>=m[h])
return;
m[h]=step;
// do something
}
完整代码见此处。
AC 记录见此处。