【搜索】BZOJ3139 HNOI2013比赛

来源:互联网 发布:淘宝互刷平台系统 编辑:程序博客网 时间:2024/04/28 14:41

BZOJ3139
搜素题一道。
n<=8乱搞都可以过。(BZOJ1306和这道题一模一样,只是n<=8

先付乱搞代码一份(只能过BZOJ1306)

#include <iostream>#include <cstdio>#define mod 1000000007using namespace std;int n, rest[15], ans, sum;void dfs(int p,int m){    if(p==n)    {        if(!rest[n])        {++ans;if(ans>=mod)ans-=mod;}        return;    }    if(m==n+1)    {        if(!rest[p])dfs(p+1,p+2);        return;    }    if((n-m+1)*3<rest[p])return;    if((n-m+1)*3==rest[p])    {        rest[p]=0;        dfs(p+1,p+2);        rest[p]=(n-m+1)*3;        return;    }    if(rest[p]>=3)    {        rest[p]-=3;        dfs(p,m+1);        rest[p]+=3;    }    if(rest[m]>=3)    {        rest[m]-=3;        dfs(p,m+1);        rest[m]+=3;    }    if(sum&&rest[p]&&rest[m])    {        --sum, --rest[p], --rest[m];        dfs(p,m+1);        ++sum, ++rest[p], ++rest[m];    }}int main(){    scanf("%d",&n);    for(int i=1;i<=n;++i)    {        scanf("%d",&rest[i]);        sum+=rest[i];    }    sum=n*(n-1)/2*3-sum;    dfs(1,2);    printf("%d\n",ans);    return 0;}

这个代码最大的问题在于没有进行记忆化。
优化一:
以剩下的队的分数按28进制数来描述。一定要把个数也加进去。之后用map进行离散化。虽然状态很多,map还是可以接受。
注:当一个队的分数已经被用完了的时候才将它放入map中。否则还需要按当前是哪一个队伍以及分配到第几场比赛上,再进行离散化。这不仅耗时,状态太多了……
优化二:改变搜索顺序。
3 1 2和1 2 3实际上是一回事。所以排一个序即可。

在上面那个代码加上优化即可。

#include <iostream>#include <cstdio>#include <map>#include <algorithm>#define LL long long int#define mod 1000000007using namespace std;int n, rest[15], ans, sum;map<LL,LL>mp;int temp[15];LL Hash(int p){    int j=1;    for(int i=p+1;i<=n;++i,++j)temp[j]=rest[i];    sort(temp+1,temp+j);    LL ans=p;    for(int i=1;i<j;++i)        ans=ans*28+temp[i];    return ans;}LL dfs(int p,int m){    if((n-m+1)*3<rest[p])return -1;    if(p==n)    {        if(!rest[n])return ans=1;        return -1;    }    if(m==n+1)    {        LL h=Hash(p);        if(mp[h])return mp[h];        return mp[h]=dfs(p+1,p+2);    }    LL ans=0, tmp;    if((n-m+1)*3==rest[p])    {        rest[p]=0;        ans=dfs(p,n+1);        rest[p]=(n-m+1)*3;        return ans?ans:-1;    }    if(rest[p]>=3)    {        rest[p]-=3;        tmp=dfs(p,m+1);        if(tmp!=-1)ans+=tmp;        rest[p]+=3;    }    if(rest[m]>=3)    {        rest[m]-=3;        tmp=dfs(p,m+1);        if(tmp!=-1)ans+=tmp;        rest[m]+=3;    }    if(sum&&rest[p]&&rest[m])    {        --sum, --rest[p], --rest[m];        tmp=dfs(p,m+1);        if(tmp!=-1)ans+=tmp;        ++sum, ++rest[p], ++rest[m];    }    return ans?ans:-1;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;++i)    {        scanf("%d",&rest[i]);        sum+=rest[i];    }    sort(rest+1,rest+n+1);    sum=n*(n-1)/2*3-sum;    printf("%d\n",dfs(1,2));    return 0;}
0 0
原创粉丝点击