P3230 [HNOI2013]比赛 题解
哈希+记忆化搜索。
正常搜索就对于每一次比赛有三种情况,第一组赢,平,第二组赢,然后判断最后分数是否符合题意即可。
剪枝1:无效性剪枝,若一个组枚举完后没有分数符合条件,返回
剪枝2:无效性剪枝,若一个组还剩的比赛全胜也无法符合分数条件,返回
剪枝3:优化搜索顺序,从分数大的来搜,得到赢局更多,情况会少。
剪枝4:设胜利数为
那么:
解方程得到比赛数量。
优化:记忆化搜索。
记录当一个组所有比赛完后,其他组的还需要得到的分数值,分数值可利用
注意:用 map 时不能因为值不为
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#define int long long
using namespace std;
const int N=15;
const int M=35;
const int mod=1e9+7;
int n,a[N],b[N],s[N],xt,yt;
map<int,int>m;
int cmp(int fi,int se)
{
return fi>se;
}
int dfs(int x,int y)
{
if(x==n)return 1;
if(y>n)
{
if(a[x]>0)return 0;
int num=0;
for(int i=x+1;i<=n;i++)b[i]=a[i];
sort(b+x+1,b+n+1);
for(int i=x+1;i<=n;i++)num=num*27+b[i];
if(m.find(num)!=m.end())return m[num];
else return m[num]=dfs(x+1,x+2);
}
if((n-y+1)*3<a[x])return 0;
int sum=0;
if(a[x]>=3&&xt)
{
a[x]-=3;
xt--;
sum+=dfs(x,y+1);
a[x]+=3;
xt++;
}
if(a[x]>=1&&a[y]>=1&&yt)
{
a[x]--;
a[y]--;
yt--;
sum+=dfs(x,y+1);
a[x]++;
a[y]++;
yt++;
}
if(a[y]>=3&&xt)
{
a[y]-=3;
xt--;
sum+=dfs(x,y+1);
a[y]+=3;
xt++;
}
return sum;
}
signed main()
{
scanf("%lld",&n);
int sum=0;
for(int i=1;i<=n;i++)scanf("%lld",&a[i]),sum+=a[i];
sort(a+1,a+1+n,cmp);
xt=sum-n*(n-1),yt=n*(n-1)/2-xt;
int ans=dfs(1,2);
printf("%lld",ans);
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通