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;

}

  

你可能感兴趣的:(ZOJ)