蓝桥杯:3000米排名预测(带限制的全排列)递归解法(DFS+状态重置)

博客介绍了如何使用递归解法(DFS+状态重置)解决蓝桥杯比赛中关于3000米长跑排名预测的问题。内容涉及输入输出格式、数据规模约定、思路解析以及AC完整代码展示。
摘要由CSDN通过智能技术生成

蓝桥杯:3000米排名预测(带限制的全排列)递归解法(DFS+状态重置)

问题描述

3000米长跑时,围观党们兴高采烈地预测着最后的排名。因为他们来自不同的班,对所有运动员不一定都了解,于是他们分别对自己了解的一些运动员的实力作出了评估,即对部分运动员做了相对排名的预测,并且告诉了可怜留守的班长。因为无聊,于是他们就组团去打Dota去了。比赛结束后他们向班长询问最后的排名,但班长不记得了,只记得他们中哪些人的预测是正确的,哪些人的预测是错误的。他们想知道比赛的排名可能是什么。
输入格式
  第一行两个整数n, m,n为运动员数量,m为围观党数量。运动员编号从0到n-1。
  接下来m行,每行为一个围观党的相对排名预测。每行第一个数c表示他预测的人数,后面跟着c个0~n-1的不同的数,表示他预测的运动员相对排名,最后还有一个数,0表示这个预测是错误的,1表示是正确的。
输出格式
  第一行一个数k为有多少种排名的可能。
  下面k行,每行一个0~n-1的排列,为某一个可能的排名,相邻的数间用空格隔开。所有排名按字典序依次输出。

样例输入

Input Sample 1:

3 2

2 0 1 1

2 1 2 0

Input Sample 2:

3 2

2 0 1 1

2 2 1 0

样例输出

Output Sample 1:

2

0 2 1

2 0 1

Output Sample 2:

1

0 1 2

数据规模和约定

1<=n<=10, 2<=c<=n, 1<=m<=10,保证数据合法,且答案中排名可能数不超过20000。对于一个排名序列,一个预测是正确的,当且仅当预测的排名的相对顺序是排名序列的一个子序列。一个预测是错误的,当且仅当这个预测不正确。

思路

对于全排列,这题判断全排列串合法否的方式比较繁琐,但是最终用时还是比较少的(上限1s)
在这里插入图片描述
这题限制条件比较多,一个一个来:

  • 将一个长度为n的预测序列分为 n-1 个 “排名对”
  • 即 1 2 3 4 可以分为 3 个排名对:<1,2> <2, 3> < 3, 4>
  • 搜索 “排名对” 中两个元素在当前全排列串中的下标位置 index1, index2
  • 如果 index1 > index2 则说明存在矛盾的排名
  • 如果 index1 <= index2 且两个元素都在都在当前全排列串中则说明该“排名对” 是合法的,即命中
  • 对于所有真假设,要求 所有单个假设的所有 “排名对” 不存在矛盾
  • 对于所有假假设,要求 不能有单个假设的所有 “排名对” 全部命中当前的全排列串

例子

在这里插入图片描述

AC完整代码

#include <iostream>

using namespace std;

#define maxlen 13

int n, m;
int ans[maxlen];		// 答案
int visited[maxlen];	// 访问控制数组

// 约束条件 
// limit[i] 存储第 i 个预测的排名序列
// limit[i][0] 是第i个预测序列的长度
// limit[i]的最后一个数字 limit[i][limit[i][0]+1] 是该预测的真假
int limit[maxlen][maxlen];

// 结果 
int cnt = 0;
int result[20001][maxlen];

// 在ans的前len+1个元素中找x的下标,未找到,返回大值,在后序判断中表示合法
int find(int x, int len)
{
   
	for(int i=0; i<=len; i++)
	<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值