非常好的一道搜索题
首先没有别的好办法就只能搜,基于对称性我只要搜对角线上半部分即可
然后有些惯用的剪枝啦什么的,具体见程序
然后代码很短,然后TLE了(但好像也有人过了)
然后就不知道怎么优化了,看到CLJ大神的空间发现这道题是可以记忆化搜索的orz
首先当搜索完某个队伍的胜负情况后,观察剩下的队伍已确定的得分和最终得分之差,我们称作剩余状态
显然,我们对后面队伍胜负的搜索得到的方案数与之前的搜索状态无关
并且,像剩下三支队伍剩余状态是1 0 3和 0 3 1是等价的,方案数相同(即顺序并不影响)
也就是说如果两次搜索的剩余状态一样,我们直接加即可,不用再搜一次
因此我们想到了记忆化搜索,对于状态的判断自然而然想到用hash

 const ch:array[..] of longint=(,,);
key=; type link=^node;
node=record
num,loc:longint;
next:link;
end; var s,c,b:array[..] of longint;
a:array[..,..] of longint;
w:array[..key] of link;
ans,u,i,n,tot:longint; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; function work(m:longint):longint; //排序,计算hash值
var i,j,p:longint;
begin
work:=;
for i:= to m- do
begin
p:=i;
for j:=i+ to m do
if b[j]>b[p] then p:=j;
swap(b[i],b[p]);
end;
for i:= to m do
work:=(work+sqr(b[i])*sqr(i)) mod key;
end; function calc(l,r:longint):longint;
var k,h:longint;
begin
h:=;
for k:= to n do
b[k]:=;
for k:=l to r do
begin
inc(h);
b[h]:=c[k]-s[k];
end;
calc:=work(h);
end; procedure add(x,y:longint);
var p:link;
i:longint;
begin
new(p);
inc(tot);
for i:= to n do
a[tot,i]:=b[i];
p^.loc:=tot;
p^.num:=y;
p^.next:=w[x];
w[x]:=p;
end; function find(x,y:longint):longint;
var p:link;
f:boolean;
i:longint; begin
p:=w[x];
while p<>nil do
begin
f:=true;
u:=p^.loc;
for i:= to n do
if (a[u,i]<>b[i]) then
begin
f:=false;
break;
end;
if f then exit(p^.num);
p:=p^.next;
end;
if y<>- then add(x,y); //没有重复的状态则插入
exit(-);
end; function dfs(t,j:longint):longint;
var k,h,q:longint;
begin
if t=n then
begin
if s[n]=c[n] then exit();
exit();
end;
if s[t]>c[t] then exit(); //剪枝,显然确定的得分不能大于最终得分的
if s[t]+(n+-j)*<c[t] then exit(); //剪枝,如果后面全胜也不能达到最终得分剪掉
if j=t+ then
begin
h:=calc(t,n);
q:=find(h,-); //-表示只是单纯的查询
if q<>- then exit(q); //记忆化
end;
q:=;
if j<=n then
begin
for k:= to do
begin
s[t]:=s[t]+ch[k];
s[j]:=s[j]+ch[-k];
if not((s[j]>c[j]) or (s[j]+(n+-t)*<c[j])) then q:=q+dfs(t,j+);
s[t]:=s[t]-ch[k];
s[j]:=s[j]-ch[-k];
end;
end
else if s[t]=c[t] then //搜完一支队伍我们就判重/记录剩余状态
begin
q:=dfs(t+,t+);
h:=calc(t+,n);
k:=find(h,q);
end;
exit(q);
end; begin
readln(n);
for i:= to n do
read(c[i]);
writeln(dfs(,));
end.

bzoj1306的更多相关文章

  1. 【BZOJ1306】[CQOI2009]循环赛(搜索)

    [BZOJ1306][CQOI2009]循环赛(搜索) 题面 BZOJ 洛谷 题解 爆搜一下,\(hash\)记录是否已经考虑过这个状态,记忆化解决问题. #include<iostream&g ...

  2. BZOJ1306: [CQOI2009]match循环赛

    [传送门:BZOJ1306] 简要题意: 有n个队伍,每个队伍都要和其他队伍比一场,赢了的队得3分,输了的队不得分,打平两队各得一分,给出每个队伍的得分,求出对战方案数 题解: DFS暴搜!!一眼就觉 ...

  3. BZOJ1306 [CQOI2009]match循环赛/BZOJ3139 [Hnoi2013]比赛[dfs剪枝+细节题]

    地址 看数据范围很明显的搜索题,暴力dfs是枚举按顺序每一场比赛的胜败情况到底,合法就累计.$O(3^{n*(n-1)/2})$.n到10的时候比较大,考虑剪枝. 本人比较菜所以关键性的剪枝没想出来, ...

  4. [BZOJ1306] [CQOI2009] match循环赛 (搜索)

    Description Input 第一行包含一个正整数n,队伍的个数.第二行包含n个非负整数,即每支队伍的得分. Output 输出仅一行,即可能的分数表数目.保证至少存在一个可能的分数表. Sam ...

  5. BZOJ3139/BZOJ1306 HNOI2013比赛/CQOI2009循环赛(搜索)

    搜索好难啊. 1.对于每个分数集合记忆化. 2.某人得分超过总分,剪枝. 3.某人之后全赢也无法达到总分,剪枝. 4.每有一场比赛分出胜负总分会多三分,而平局则会多两分.某人的分出胜负场次或平局场次超 ...

  6. 【搜索】【剪枝】bzoj1306 [CQOI2009]match循环赛

    dfs+剪枝*4(通过得很勉强): 1.只枚举一半的比赛,另一半直接得出. 2.处理前缀和,若大于目标得分则剪枝 3.前缀和加上若接下来全胜的得分 仍小于 目标得分,则剪枝. 4.枚举到每个人的最后一 ...

  7. bzoj1306: [CQOI2009]match循环赛(模拟爆搜)

    Input第一行包含一个正整数n,队伍的个数.第二行包含n个非负整数,即每支队伍的得分.Output输出仅一行,即可能的分数表数目.保证至少存在一个可能的分数表.Sample Input 6 5 6 ...

  8. 【BZOJ1306】match循环赛

    预先警告:我的做法代码量比较大 看完题目后看到数据n<=8, 不难想到这题可以写深搜来做 分析 比如说以数据: 3 3 3 3 为例子, 进行了三场比赛:AB AC BC: 我们只要搜索每场比赛 ...

  9. 8.3-8.7 usaco

    summary:38 vijos1002:青蛙跳河. dp+压缩.距离大于100可以直接%100.然后数据范围小了很多可以dp了. #include<cstdio> #include< ...

随机推荐

  1. HttpWebRequest结合HtmlAgilityPack实现网页form提交

    年前一个项目,需要在某个系统实现系统自动操作. 系统页面使用form提交,页面参数较多,也参数设计一系列计算逻辑,改动一个值,其他值自动改变. 传统方法使用正则表达式匹配参数,构建post参数进行请求 ...

  2. 简洁JS 日历控件 支持日期和月份选择

    原文出处 以下这个JS日历控件是我的闲暇之余自己编写的,所有的代码全部在IE7/IE8/Firefox下面测试通过, 而且可以解决被iframe层遮盖的问题.现在只提供两种风格(简洁版和古典版)和两种 ...

  3. DOM操作--表格点击行变色

    点击表格行变色,这种网页效果应该还是比较常见的.大家应该看见了,我这里的效果是用DOM操作实现的,那么很多人会问什么是DOM操作,贴出代码之前我就和大家解释一下什么是DOM操作: DOM是Docume ...

  4. tar 解压缩

    解压 tar –xvf file.tar //解压 tar包 tar -xzvf file.tar.gz //解压tar.gz tar -xjvf file.tar.bz2   //解压 tar.bz ...

  5. ios专题 -动画

    知识点 : 1)ios 核心动画的基础是图层.图层的基础是CALayer,它是所有核心图层类的父类. 2)CATransaction是核心动画类负责协调多个动画原子显示更新.事务支持嵌套使用. 3)图 ...

  6. [转]setTimeout() 函数未定义错误

    用 setTimeout("showMe()",1000) 时出现 showMe is not defined 错误.这是由于showMe() 函数不在 setTimeout 调用 ...

  7. windows phone 之ListBox模板选择

    有时做项目时,会遇到一种情况:需要把获取到的数据集合显示到首页,比如新闻,但是: 新闻也分类别啊,比如:图片类新闻.文字类新闻.视频类新闻. 那我们可能采用的模板就不一样了,那么,如何根据类别来选择模 ...

  8. C++静态成员函数访问非静态成员的几种方法

    大家都知道C++中类的成员函数默认都提供了this指针,在非静态成员函数中当你调用函数的时候,编译器都会“自动”帮你把这个this指针加到函数形参里去.当然在C++灵活性下面,类还具备了静态成员和静态 ...

  9. Java学习----集合函数

    1.List----有序的collection(序列) 与数组的不同:数据类型可以相同可以不同,数组的长度是预先定义好的,集合的长度也是预先定义好的,但是长度会随着元素的增加而增加 ArrayList ...

  10. c++相关知识回顾

    1.typedef typedef用来定义同类型的同义词.如: typedef unsingned int size_t; typedef int ptrdiff_t; typedef T * ite ...