BZOJ 1860: [Zjoi2006]Mahjong麻将
题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1860
/*
* BZOJ 1860: [Zjoi2006]Mahjong麻将
*
* 分析:
* 据说有DP解,暂时没想出来。。。直接暴力dfs+hash
* dfs(pos,two,state):pos表示当前的位置,two表示是否有对,state表示状态
* 暴力枚举四种情况,然后每次进行搜索前进行hash判重。
* hash判重时使用像池子法一样的方式解决冲突问题。
*
* */
#include <cstdio> #include <iostream> #include <cstring> using namespace std; const int maxm = 2e5+10; const int mod = 99997; const int maxn = 105; const int n = 100; const int seed = 103; typedef unsigned long long ll; ll p[maxn]; int a[maxn]; int po[mod+3],tol; struct Hash{ ll val; int next; }edge[maxm]; void ins(ll x){ //insert x int y = int(x%mod); edge[++tol].val = x; edge[tol].next = po[y]; po[y] = tol; } bool has(ll x){ //has x ? int y = int(x%mod); for(int i=po[y];i;i=edge[i].next) if(edge[i].val==x) return true; return false; } bool dfs(int pos,bool two,ll state){ if(has(state)) return false; ins(state); while(pos<=n&&a[pos]==0) pos ++; if(pos>n) return two; if(pos+2<=n&&a[pos+1]&&a[pos+2]){ //three continous a[pos] --; a[pos+1] --; a[pos+2] --; if(dfs(pos,two,state-p[pos]-p[pos+1]-p[pos+2])) return true; a[pos] ++; a[pos+1] ++; a[pos+2] ++; } if(a[pos]>=3){ //three a[pos] -= 3; if(dfs(pos,two,state-p[pos]*3)) return true; a[pos] += 3; } 1 if(a[pos]>=4){ // four a[pos] -= 4; if(dfs(pos,two,state-p[pos]*4)) return true; a[pos] += 4; } if(a[pos]>=2 && !two){ // pair a[pos] -= 2; //对于一对的特殊判断,比如可能存在5 = 3 + 2 = 4 +1(连续型但之前搜过不行) if(dfs(pos,true,state-p[pos]*2-p[n+1])) return true; a[pos] += 2; } return false; } int main(){ int ncase,x; cin>>ncase; p[1] = 1; for(int i=2;i<=n+1;i++) p[i] = p[i-1]*seed; while(ncase--){ ll state = 0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); state *= seed; state += a[i]; } state *= seed; //对于一对的特殊判断 state ++; memset(po,0,sizeof(po)); tol = 0; dfs(1,false,state)?puts("Yes"):puts("No"); } return 0; }