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

[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;
}
posted @ 2018-10-09 21:41 Menteur_Hxy 阅读( ...) 评论( ...) 编辑 收藏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值