L2-047 锦标赛
解题思路
首先输入的是k,代表游戏一共进行的轮数,然后接下来的k行,每行给出每轮中各个比赛的失败者。
最后一行给出冠军。
这个过程就是淘汰赛,像那个口袋妖怪绿宝石对战帐篷那个图一样,显然我们这里可以发现,这是一个树结构,并且是一个完全二叉树(这里表述可能不太准确,我是想表达每场比赛的胜者进入父节点的意思)。对于一个完全二叉树,其最突出的性质就是对于每个结点i,其子节点下标为 2×i 与 2×i+1 。而且这里还是一个大根堆。
本题最后一定是要建树的
然而这里的建树并没有什么规律(模拟一下就知道),只能采用暴力枚举的方法,如果最后枚举有一个解成立(成功建且符合大根堆),就直接结束dfs函数并准备输出。
dfs函数的过程是:由上到下,只有最后一轮的比赛是已知的,而最后一轮比赛的两个选手可以往下填,(这里是把每场比赛看成一个结点,但是每个节点存有胜者和败者,可以采用结构体),结构是这样的
//u是根节点
//只需要把父结点的两个人分配给子节点的赢家
tree[2*u].w = tree[u].w;
tree[2*u+1].w = tree[u].l;
//由于有左右两个子树,都要深搜一下。
if(dfs(2*u,size) && dfs(2*u+1,size)) return true;
//这只是一种情况,显然这里要回溯一下然后进行另一种情况的dfs
swap(tree[2*u].w,tree[2*u+1].w);
if(dfs(2*u,size) && dfs(2*u+1,size)) return true;
我寻思🤔写题解的时候六得很,实战的时候一个都写不对,不过这里的dfs函数本身确实不难,是最简单的那种

然后是这题输入输出的问题(也是一个难点)
首先总结点数是 (\(2^k - 1\)) 个,输入的时候是从最后一层开始输入
for(int i = k-1 ; i >= 0 ; i-- )
{
int st = 1 << i;
int ed = 1 << (i+1);
for(int j = st ; j < ed ; j ++)
{
cin>>tree[j].l;
}
}
然后是输出,最后只需要输出最后一层,每个结点的输赢者
int st = 1 << (k-1);
int ed = 1 << k;
for(int i = st ; i < ed ; i++)
{
cout<<tree[i].w<<" "<<tree[i].l;
if(i != ed - 1) cout<<" ";
}
ac✅️代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1 << 20;
struct Node
{
int w,l;
}nodes[N];
int k;
bool dfs(int u, int size)//dfs的作用是看这条路行不行
{
if(u > size) return true;//结束条件
if(nodes[u].l > nodes[u].w) return false;//剪枝
//接下来有两种选择,第一种是:胜者给左子树,败者给右子树
nodes[2 * u].w = nodes[u].w;
nodes[2 * u + 1].w = nodes[u].l;
if(dfs(2 * u , size) && dfs(2 * u + 1 ,size)) return true;
//如果第一种行不通,再选第二种,交换一下
swap(nodes[2 * u].w , nodes[2 * u + 1].w);
if(dfs(2 * u , size) && dfs(2 * u + 1 , size)) return true;
//如果都不行,就返回false
return false;
}
int main()
{
if(!(cin>>k)) return 0;
for(int i = k-1 ; i >= 0 ; i-- )
{
int st = 1 << i;
int ed = 1 << (i+1);
for(int j = st ; j < ed ; j ++)
{
cin>>nodes[j].l;
}
}
cin>>nodes[1].w;//还需要输入一个赢家
int treesize = (1 << k) - 1;//数的大小
if(dfs(1,treesize))
{
//由于每2个人绑定为一个节点,所以最后的节点数只有一半
//编号为2^(k-1)到2^k - 1
int st = 1 << (k-1);
int ed = 1 << k;
for(int i = st ; i < ed ; i++)
{
cout<<nodes[i].w<<" "<<nodes[i].l;
if(i != ed - 1) cout<<" ";
}
cout<<endl;
}
else cout<<"No Solution"<<endl;
return 0;
}

浙公网安备 33010602011771号