BZOJ3139
搜素题一道。
n<=8
乱搞都可以过。(BZOJ1306和这道题一模一样,只是
n<=8
)
优化一:
以剩下的队的分数按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 1000000007
using 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;
}