BZOJ1306 [CQOI2009]match循环赛/BZOJ3139 [Hnoi2013]比赛[dfs剪枝+细节题]
看数据范围很明显的搜索题,暴力dfs是枚举按顺序每一场比赛的胜败情况到底,合法就累计。$O(3^{n*(n-1)/2})$。n到10的时候比较大,考虑剪枝。
本人比较菜所以关键性的剪枝没想出来,但由于数据较水,20个点就T了2个。依旧记下剪枝方案,没想到的用下划线和红笔标注:
- 剪枝一:个人觉得应该将数组从小到大排序来搜,这样感觉起来状态少一些。实测有时和从大到小相差不大,但有时可能有效。
- 剪枝二:如果当前选手就算赢了所有剩下的场也到不了分数,剪掉。弱剪枝。
- 剪枝三:如果剩下所有场全是决出胜负的也没办法将分数累到总的要求得分,剪掉;就算全平局也超过了要求的总得分,剪掉。基于这种剪枝和上面一样效果不大,没写上去。
- 剪枝四:当一个选手和后面选手的比赛枚举完毕时看他分数够不够,不够就不往下搜了。
- 剪枝五:记忆化。由于每个队得分数字都不太大,可以将一个选手和后面选手全比完时剩下的没有互相比的几个队看成一个状态。即剩下的几个队顺序如何不重要,重要的是要看他们还差多少分满足条件。比如最后4个队分别还差3,2,4,3分,另一种情况剩下四个队还差2,3,3,4分,两种是等效的,可以将其排序后用hash记录下来,当以后遇到相同转态直接返回。
- 剪枝六:通过方程求解相关量:设决出胜负的比赛x场,打平的比赛y场,总的分数为s,则有方程组$①3x+2y=s$ $②x+y=\frac{n(n-1)}{2}$ 然后可确定具体的胜负或打平比赛有多少场,然后带入剪枝。
然后是对于记忆化的几点补充,这个坑死我了。
- 哈希可以用拖链表方法,这次不想写了,直接上裸的hash。注意初始时清-1,因为可能是会存0这样的值的。
- 记忆化看似每次很耗时间,到搜索终点就要线性算一下hash。但是发现本质相同的状态只有几千个左右,很多时候我发现状态相同了直接返回记忆化的值,会把原来可能的指数级转换为线性的,所以总体是飞快的。
- 最坑的地方:关于hash值的计算。由于分数中存在0,所以算hash值的时候会有疏漏。比如1,0,1和1,1.而这两种答案是不一样的。所以要强制每个数都加上一点点。
WA记录:(非常重要)注意hash计算过程中出现数字0的情况!
BZOJ1306 [CQOI2009]match循环赛
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#define dbg(x) cerr<<#x<<" = "<<x<<endl
#define ddbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl
using namespace std;
typedef long long ll;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const ll P=,base=;
int n,T,sx,sy;
int rest[],tmp[],H[P],sum;
inline int dfs(int i,int j){//ddbg(i,j),dbg(ans);
if(i==n)return !rest[i];
if(j>n){
if(rest[i])return ;
for(register int k=i+;k<=n;++k)tmp[k]=rest[k];
sort(tmp+i+,tmp+n+);int ha=;
for(register int k=i+;k<=n;++k)ha=(ha*base+tmp[k]+)%P;//¡ï¡ï¡ï¡ï¡ï
if(~H[ha])return H[ha];
return H[ha]=dfs(i+,i+);
}
if(*(n-j+)<rest[i])return ;
int ret=;
if(rest[i]>=)rest[i]-=,ret+=dfs(i,j+),rest[i]+=;
if(rest[i]&&rest[j])--rest[i],--rest[j],ret+=dfs(i,j+),++rest[i],++rest[j];
if(rest[j]>=)rest[j]-=,ret+=dfs(i,j+),rest[j]+=;
return ret;
} int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
memset(H,-,sizeof H);
read(n);for(register int i=;i<=n;++i)sum+=read(rest[i]);
sort(rest+,rest+n+);printf("%d\n",dfs(,));
return ;
}
BZOJ3139 [Hnoi2013]比赛
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#define dbg(x) cerr<<#x<<" = "<<x<<endl
#define ddbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl
using namespace std;
typedef long long ll;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const ll P=,base=,MOD=1e9+;
int n,T,sx,sy;
int rest[],tmp[],H[P],sum,tot,flag;
inline ll dfs(int i,int j){//ddbg(i,j),dbg(ans);
if(i==n)return !rest[i];
if(j>n){
if(rest[i])return ;
for(register int k=i+;k<=n;++k)tmp[k]=rest[k];
sort(tmp+i+,tmp+n+);ll ha=;
for(register int k=i+;k<=n;++k)ha=(ha*base+tmp[k]+)%P;
if(~H[ha])return H[ha];
return H[ha]=dfs(i+,i+);
}
if(*(n-j+)<rest[i])return ;
ll ret=;
if(rest[i]>=&&sx)rest[i]-=,--sx,ret+=dfs(i,j+),rest[i]+=,++sx;
if(rest[i]&&rest[j]&&sy)--rest[i],--rest[j],--sy,ret+=dfs(i,j+),++rest[i],++rest[j],++sy;
if(rest[j]>=&&sx)rest[j]-=,--sx,ret+=dfs(i,j+),rest[j]+=,++sx;
return ret%MOD;
} int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
memset(H,-,sizeof H);
read(n);for(register int i=;i<=n;++i)sum+=read(rest[i]);
sx=sum-n*n+n,sy=*(n-)*n/-sum;
sort(rest+,rest+n+);
return printf("%lld\n",dfs(,)),;
}
BZOJ1306 [CQOI2009]match循环赛/BZOJ3139 [Hnoi2013]比赛[dfs剪枝+细节题]的更多相关文章
- 【搜索】【剪枝】bzoj1306 [CQOI2009]match循环赛
dfs+剪枝*4(通过得很勉强): 1.只枚举一半的比赛,另一半直接得出. 2.处理前缀和,若大于目标得分则剪枝 3.前缀和加上若接下来全胜的得分 仍小于 目标得分,则剪枝. 4.枚举到每个人的最后一 ...
- bzoj1306: [CQOI2009]match循环赛(模拟爆搜)
Input第一行包含一个正整数n,队伍的个数.第二行包含n个非负整数,即每支队伍的得分.Output输出仅一行,即可能的分数表数目.保证至少存在一个可能的分数表.Sample Input 6 5 6 ...
- BZOJ1306: [CQOI2009]match循环赛
[传送门:BZOJ1306] 简要题意: 有n个队伍,每个队伍都要和其他队伍比一场,赢了的队得3分,输了的队不得分,打平两队各得一分,给出每个队伍的得分,求出对战方案数 题解: DFS暴搜!!一眼就觉 ...
- [BZOJ1306] [CQOI2009] match循环赛 (搜索)
Description Input 第一行包含一个正整数n,队伍的个数.第二行包含n个非负整数,即每支队伍的得分. Output 输出仅一行,即可能的分数表数目.保证至少存在一个可能的分数表. Sam ...
- [BZOJ3139][HNOI2013]比赛(搜索)
3139: [Hnoi2013]比赛 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1439 Solved: 719[Submit][Status] ...
- bzoj 1306: [CQOI2009]match循环赛【dfs+剪枝】
大力剪枝,最后洛谷上还开了o2才过-- 大概这样剪枝: 1.搜索中,一个队当前得分超过要求或者一个队剩下的比赛场数全赢也达不到要求则return: 2.注意到如果平局,最总分的贡献是2,否则是3,所以 ...
- [BZOJ3139][HNOI2013] 比赛
Description 沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛.此次联 赛共N支球队参加,比赛规则如下: (1) 每两支球队之间踢一场比赛. (2) 若平局,两支球队各 ...
- 【BZOJ1306】match循环赛
预先警告:我的做法代码量比较大 看完题目后看到数据n<=8, 不难想到这题可以写深搜来做 分析 比如说以数据: 3 3 3 3 为例子, 进行了三场比赛:AB AC BC: 我们只要搜索每场比赛 ...
- bzoj千题计划294:bzoj3139: [Hnoi2013]比赛
http://www.lydsy.com/JudgeOnline/problem.php?id=3139 队伍的顺序不会影响结果 将队伍的得分情况作为状态,记忆化搜索 就是先搜索第一只队伍的得分情况, ...
随机推荐
- 在使用DapperExtensions时遇到"其他信息: ConnectionString 属性尚未初始化。"错误
今天在使用在使用DapperExtensions时遇到"其他信息: ConnectionString 属性尚未初始化."错误. //return conn.GetList<T ...
- office web apps安装部署,配置https,负载均衡(二)域控制器安装并配置域账号
域控制器对服务器的要求不高,我们这里以windows server 2008R2为例 系统要求:windows server 2008R2 笔者也尝试使用了windows server 2012R2, ...
- 云计算共享组件--Memcache缓存系统(4)
一.缓存系统 一.静态web页面: 1.在静态Web程序中,客户端使用Web浏览器(IE.FireFox等)经过网络(Network)连接到服务器上,使用HTTP协议发起一个请求(Request),告 ...
- 必须要掌握的linux目录路径知识
一./etc/sysconfig/network-scripts/ifcfg-en33 配置网络地址及GW等. 下面图片是一些常用的linux命令: nmtui(setup)---------- ...
- 布隆过滤器(Bloom Filter)原理以及应用
应用场景 主要是解决大规模数据下不需要精确过滤的场景,如检查垃圾邮件地址,爬虫URL地址去重,解决缓存穿透问题等. 布隆过滤器(Bloom Filter)是1970年由布隆提出的.它实际上是一个很长的 ...
- rabbitmq五种消息模型整理
目录 0. 配置项目 1. 基本消息模型 1.1 生产者发送消息 1.2 消费者获取消息(自动ACK) 1.3 消息确认机制(ACK) 1.4 消费者获取消息(手动ACK) 1.5 自动ACK存在的问 ...
- Python 入门 之 异常处理
Python 入门 之 异常处理 1.异常处理 (1)程序中的错误分为两种 <1> 语法错误 (这种错误,根本过不了Python解释器的语法检测,必须在程序执行前就改正) # 语法错误示范 ...
- Hive 教程(七)-DML基础
DML,Hive Data Manipulation Language,数据操作语言: 通俗理解就是数据库里与数据的操作,如增删改查,统计汇总等: Loading files into tables ...
- LeetCode题解: LRU Cache 缓存设计
LeetCode题解: LRU Cache 缓存设计 2014年12月10日 08:54:16 邴越 阅读数 1101更多 分类专栏: LeetCode 版权声明:本文为博主原创文章,遵循CC 4 ...
- HTML和CSS学习
HTML和CSS HTML 基础讲解 要点: 标记语言不是编程语言 .html和.htm都是html文档的后缀 标签有围堵和自闭两类 开始标签中可以定义属性,属性的值要用引号引起来 H5一般用于移动端 ...