bzoj千题计划294:bzoj3139: [Hnoi2013]比赛

http://www.lydsy.com/JudgeOnline/problem.php?id=3139

 

队伍的顺序不会影响结果

将队伍的得分情况作为状态,记忆化搜索

 

就是先搜索第一只队伍的得分情况,即为他分配分数

当第一只队伍的分数分配完时,它与其他队伍的比拼会使其他队伍也分配到了一定的分数

将其他队伍分配到的分数 这个状态 哈希

然后第二支队……,这就是子问题

 

啊啊啊,我也不知道我在说啥了

 

myl考场AC tql!!!

 

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>

#define N 11

using namespace std;

typedef long long LL;

const int mod=1e9+7;

int n,w[N];

map<LL,int>mp[N];

LL gethash(int *b,int p)
{
    LL S=0;
    for(int i=p;i<=n;++i) S=S*28+b[i];
    return S;
}

int dfs(int *val,int l,int r)
{
    if(l==r)
    {
        if(val[l]) return 0;
        if(l==n) return 1;
        int b[N];
        memcpy(b,val,sizeof(b));
        sort(b+l+1,b+n+1);
        LL S=gethash(b,l+1);
        if(mp[l+1].find(S)==mp[l+1].end()) mp[l+1][S]=dfs(b,l+1,n);
        return mp[l+1][S];
    }
    if(3*(r-l)<val[l]) return 0;
    int tot=0;
    if(val[l]>=3)
    {
        val[l]-=3;
        tot+=dfs(val,l,r-1);
        tot-=tot>=mod ? mod : 0;
        val[l]+=3;
    }
    if(val[l] && val[r])
    {
        val[l]--; val[r]--;
        tot+=dfs(val,l,r-1);
        tot-=tot>=mod ? mod : 0;
        val[l]++; val[r]++;
    }
    if(val[r]>=3)
    {
        val[r]-=3;
        tot+=dfs(val,l,r-1);
        tot-=tot>=mod ? mod : 0;
        val[r]+=3;
    }
    return tot;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&w[i]);
    printf("%d",dfs(w,1,n));
}

 

posted @ 2018-03-20 16:28  TRTTG  阅读(233)  评论(13编辑  收藏  举报