题意:

一共NNN个人,给出任意两个人之间的胜负关系,你的编号是MMM。现在需要安排一棵竞赛树使得MMM能够胜出,问使竞赛树高度最小且MMM获胜的安排方案一共有多少个。(1≤N≤16)(1\leq N\leq 16)(1≤N≤16)


思路:

根据题意以及数据范围,可以很明显的发现这是一个状压dpdpdp,因此我们来考虑dpdpdp的状态。

既然是状态,那肯定要记录当前的状态,即选了哪些人,然后还要记录当前的胜利者,以及当前树的高度,因此dp[i][j][k]dp[i][j][k]dp[i][j][k]表示iii状态下,胜出者为jjj,树高度为kkk的安排方案数。

然后采用记忆化搜索,求取dp[i][j][k]dp[i][j][k]dp[i][j][k]时将iii分为两个子状态xxx、yyy,然后递归求取dp[x][j][k−1]dp[x][j][k-1]dp[x][j][k−1],枚举mmm为yyy状态下的胜利者并且会输给jjj,求取dp[y][m][k]dp[y][m][k]dp[y][m][k]。具体细节见代码。


代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define LOG1(x1,x2) cout << x1 << ": " << x2 << endl;
#define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl;
#define LOG3(x1,x2,y1,y2,z1,z2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << " , " << z1 << ": " << z2 << endl;
typedef long long ll;
typedef double db;
const int N = 1e5+100;
const int M = 1e5+100;
const db EPS = 1e-9;
using namespace std;template<class T> int getbit(T s, int i) { return (s >> i) & 1; }
template<class T> T onbit(T s, int i) { return s | (T(1) << i); }
template<class T> T offbit(T s, int i) { return s & (~(T(1) << i)); }
template<class T> int cntbit(T s) { return __builtin_popcount(s);}int c[20][20],n,win,h[20];
ll dp[1<<16][17][7];ll solve(int stat,int m,int height){if(dp[stat][m][height] != -1) return dp[stat][m][height];if(cntbit(stat) == 1){if(getbit(stat,m-1)) return dp[stat][m][height] = 1ll;else return dp[stat][m][height] = 0;}for(int i = (stat-1)&stat; i >= 1; i = (i-1)&(stat)){ //枚举子集int x = i, y = stat-i;if(!getbit(x,m-1) || h[cntbit(x)] > height-1 || h[cntbit(y)] > height-1) continue;// if(height-1 > cntbit(x) || height-1 > cntbit(y)) continue;ll ans1 = solve(x,m,height-1);ll ans2 = 0;rep(j,1,n)if(getbit(y,j-1) && c[m][j] == 1) ans2 += solve(y,j,height-1);if(dp[stat][m][height] == -1) dp[stat][m][height] = ans1*ans2; else dp[stat][m][height] += ans1*ans2;}return max(0ll,dp[stat][m][height]);
}int main()
{freopen("f.in","r",stdin);freopen("f.out","w",stdout);scanf("%d%d",&n,&win);rep(i,1,n)rep(j,1,n) scanf("%d",&c[i][j]);rep(i,1,16) h[i] = (log(i-0.5)/log(2))+2;memset(dp,-1,sizeof dp);printf("%lld\n",max(0ll,solve((1<<n)-1,win,h[n])));return 0;
}

【Gym - 100837 F】Controlled Tournament【竞赛树 状态压缩】相关推荐

  1. SDUT3930 - 皮卡丘的梦想2(线段树状态压缩)

    皮卡丘的梦想2 Description 一天,一只住在 501 实验室的皮卡丘决定发奋学习,成为像 LeiQ 一样的巨巨,于是他向镇上的贤者金桔请教如何才能进化成一只雷丘. 金桔告诉他需要进化石才能进 ...

  2. 【SGU 448】Controlled Tournament(状态压缩动态规划)

    题目链接 [SGU 448]Controlled Tournament 题目大意 给定比赛人员个数nnn,你希望赢的人的编号m" role="presentation" ...

  3. C++数据结构与算法 竞赛树, 二叉搜索树

    竞赛树: tournament tree, 也是以可完全二叉树,所以使用数组描述效率最好,竞赛树的基本操作是替换最大(小)元素 赢者树和输者树: 为了便于实现,需要将赢者树限制为完全二叉树.n个参与者 ...

  4. 《数据结构、算法与应用 —— C++语言描述》学习笔记 — 竞赛树

    <数据结构.算法与应用 -- C++语言描述>学习笔记 - 竞赛树 一.赢者树 二.二叉树的数组描述(补充) 1.声明 2.实现 三.赢者树 1.抽象数据类型 2.赢者树的表示 3.声明 ...

  5. 《算法竞赛进阶指南》打卡-基本算法-AcWing 93. 递归实现组合型枚举:递归与递推、dfs、状态压缩

    文章目录 题目解答 题目链接 题目解答 分析: 此题和笔者另一篇博文很像,只不过是限定了个数.<算法竞赛进阶指南>打卡-基本算法-AcWing 92. 递归实现指数型枚举:递推与递归.二进 ...

  6. 《算法竞赛进阶指南》打卡-基本算法-AcWing 91. 最短Hamilton路径:位运算、状态压缩dp、dp

    文章目录 题目解答 题目链接 题目解答 分析: 状态压缩dp是用二进制数来表示状态. 数据范围n = 20, 那么状态总量就是2202^{20}220个状态. 可以按照以下思路去思考: 哪些点被用过 ...

  7. CodeForces - 620E New Year Tree(线段树+dfs序+状态压缩)

    题目链接:点击查看 题目大意:给出一棵无向树,每个节点都有一种颜色,接下来时m次操作: 1 x y:将x及其子树染成y的颜色 2 x:查询x及其子树上共有多少种不同的颜色 题目分析:看完这个题的第一反 ...

  8. POJ 2777 Count Color (线段树区间修改 + 状态压缩)

    题目链接:POJ 2777 Count Color [题目大意] 给你 n 块板子, 编号1--n , 板子的颜色最多30种, 初始时  板子的颜色都是 1: 有两种操作 1 .把给定区间的板子染成一 ...

  9. LeetCode第 57 场力扣夜喵双周赛(差分数组、单调栈) and 第 251 场力扣周赛(状态压缩动规,树的序列化,树哈希,字典树)

    LeetCode第 57 场力扣夜喵双周赛 离knight勋章越来越近,不过水平没有丝毫涨进 1941. 检查是否所有字符出现次数相同 题目描述 给你一个字符串 s ,如果 s 是一个 好 字符串,请 ...

  10. 设森林F对应的二叉树为B,它有m个结点,B的根p,p右子树结点个数n,森林F中第一棵树的结点个数

    题目:设森林F对应的二叉树为B,它有m个结点,B的根p,p右子树结点个数n,森林F中第一棵树的结点个数 设森林F对应的二叉树为B :它的意思就是将森林F转换为二叉树. 它有m个结点 :这颗二叉树总共有 ...

最新文章

  1. Android 异常: failed to connect to localhost/127.0.0.1
  2. 史上最通俗易懂的IPFS入门介绍:01
  3. 18年总结及19年展望
  4. 4月27日微软云训练营活动-现场图集
  5. 在 Visual C++ 中使用内联汇编
  6. docker 安装kafka(快速)
  7. 中文NER的正确打开方式: 词汇增强方法总结 (从Lattice LSTM到FLAT)
  8. java安装没有jdk文件_java文件在没有安装jdk的windows下运行。
  9. 安信可nbiot模块_安信可wifi模组特征
  10. 浅谈图像识别技术原理与价值
  11. 给重回正路的大二学生:戒急戒躁中前行
  12. word中全部数字、大小写字母、标点更改为新罗马字体Times News Romans
  13. 视音频编解码技术零基础学习方法
  14. 爬虫中使用selenium实现对斗鱼直播的各个房间标题、主播id,直播内容类型和热度信息的爬取
  15. aspnet+sqlserver同学录校友录网站系统
  16. 如何下载并安装VMware虚拟机。
  17. 一个与众不同的苹果--苹果产品制胜之道
  18. 最新体感:超级街霸4
  19. STM32F103详细频率测量过程
  20. 3C产品认证免收费用项目

热门文章

  1. 我对Backbone的认识
  2. 基于OpenCV库的Gabor滤波器的实现
  3. 保护数据库安全十七招
  4. 【前端】相信你会用到的一篇笔记---CSS篇(1)
  5. 安卓项目连接后台服务器,android云后端服务器
  6. java提取日志sql,通过Java程序抽取日志中的sql语句
  7. php try catch 作用域,浅谈PHP中try{}catch{}的使用方法
  8. 怎么重装python_如何部署Jupyter Notebook用于交互式Python开发?
  9. go语言环境搭建及vim高亮设置
  10. nyoj1110 一个简单数学题