东华OJ 基础题134 3000米排名预测——难度易

问题描述 :

3000米长跑时,围观党们兴高采烈地预测着最后的排名。因为他们来自不同的班,对所有运动员不一定都了解,于是他们分别对自己了解的一些运动员的实力作出了评估,即对部分运动员做了相对排名的预测,并且告诉了可怜留守的班长。因为无聊,于是他们就组团去打Dota去了。比赛结束后他们向班长询问最后的排名,但班长不记得了,只记得他们中哪些人的预测是正确的,哪些人的预测是错误的。他们想知道比赛的排名可能是什么。

输入说明 :

第一行两个整数n, m,n为运动员数量,m为围观党数量。运动员编号从0到n-1。

接下来m行,每行为一个围观党的相对排名预测。每行第一个数c表示他预测的人数,后面跟着c个0~n-1的不同的数,表示他预测的运动员相对排名,最后还有一个数,0表示这个预测是错误的,1表示是正确的。

数据规模和约定

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

输出说明 :

第一行一个数k为有多少种排名的可能。

下面k行,每行一个0~n-1的排列,为某一个可能的排名,每个数字后有一个空格(即:行尾也有一个空格)。所有排名按字典序依次输出。

比如,输入:

3 2
2 0 1 1
2 2 1 0

则输出:

1
0 1 2 

输入范例 :

3 2
2 0 1 1
2 1 2 0

输出范例 :

2
0 2 1 
2 0 1 

完整C++代码

感觉有点逆天,这才难度易?

#include <bits/stdc++.h>

using namespace std;

int n, m;
int visit[10] = {0};
vector<vector<int>> good, bad, ans;
vector<int> res(10);

int check() {
	//good
	for (int i = 0; i < good.size(); i++) {
		int k = 0;
		for (int j = 0; j < n; j++) {
			if (good[i][k] == res[j]) {
				k++;
				if (k == good[i].size()) break;
			}
		}
		if (k != good[i].size()) return 0;
	}
	//bad
	for (int i = 0; i < bad.size(); i++) {
		int k = 0;
		for (int j = 0; j < n; j++) {
			if (bad[i][k] == res[j]) k++;
			if (k == bad[i].size()) return 0;
		}
	}
	return 1;
}

void dfs(int step) {
	if (step == n) {
		if (check()) {
			ans.push_back(res);
		}
		return;
	}
	for (int i = 0; i < n; i++) {
		if (visit[i] == 0) {
			visit[i] = 1;
			res[step] = i;
			dfs(step + 1);
			visit[i] = 0;
		}
	}
}

int main()
{
	cin >> n >> m;
	int c, t;
	while (m--) {
		cin >> c;
		vector<int> v;
		for (int i = 0; i < c; i++) {
			cin >> t;
			v.push_back(t);
		}
		cin >> t;
		if (t) good.push_back(v);
		else bad.push_back(v);
	}
	dfs(0);
	cout << ans.size() << endl;
	for (int i = 0; i < ans.size(); i++) {
		for (int j = 0; j < n; j++) {
			cout << ans[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

😋欢迎大伙私信或者评论区交流讨论😋

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值