[luogu3230 HNOI2013] 比赛 (搜索+Hash)

传送门

Solution

搜索加Hash记录状态,记忆化搜索,需要注意顺序无关答案

Code

//By Menteur_Hxy
#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define Re register
#define Fo(i,a,b) for(Re int i=(a),_=(b);i<=_;i++)
#define Ro(i,a,b) for(Re int i=(b),_=(a);i>=_;i++)
using namespace std;
typedef long long LL;

inline int read() {
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
	while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
	return x*f;
}

const int N=10,bas=137,MOD=1e9+7;
int n;
LL ans;
int p[4]={3,1,0,0};
int da[N],nw[N],b[N];

map<LL,int> M;

LL Hash(int x) {
	LL res=x;
	Fo(i,x,n) b[i]=da[i]-nw[i]; sort(&b[x],&b[n]);
	Fo(i,x,n) res=(res*bas%MOD+b[i])%MOD;
	return res;
}

LL dfs(int x,int y) {
	if(nw[x]>da[x]||nw[y]>da[y]) return 0;
	if(da[x]-nw[x]>(y-x)*3) return 0;
	if(x==n) return 1;
	LL res=0;
	if(y==x+1) {
		int d=da[x]-nw[x];
		if(d==2||d>3) return 0;
		nw[x]+=d,nw[y]+=p[d];
		LL tmp=Hash(x+1);
		if(M.count(tmp)) res=M[tmp];
		else res=M[tmp]=dfs(x+1,n);
		nw[x]-=d,nw[y]-=p[d];
		return res;
	}
	if(da[x]-nw[x]>=3) {nw[x]+=3;res+=dfs(x,y-1);nw[x]-=3;}
	if(da[x]>nw[x]&&da[y]>nw[y]) {nw[x]++;nw[y]++;res+=dfs(x,y-1);nw[x]--;nw[y]--;}
	if(da[y]-nw[y]>=3) {nw[y]+=3;res+=dfs(x,y-1);nw[y]-=3;}
	return res;
}

int main() {
	n=read();
	Fo(i,1,n) da[i]=read();
	sort(da+1,da+1+n);
	ans=dfs(1,n);
	printf("%lld",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9763113.html