标签:2019E1 ++ 妙趣 排好序 dfs int au 序列 排序
妙妙趣排序
题目
本题中:
一个即将排好序的序列定义为:将这个序列去除至多一个值后,新序列是严格递增的。
一个过滤器[u,v]定义为:一个序列a经过过滤器[u,v]后,au=min(au,av),av=max(au,av),其他值不变。
妙妙趣排序器由k个过滤器组成,一个序列的妙妙趣排序需要依次经过排序器的k个过滤器。
那么请问,1~n的全排列中,有几个序列经过给定的妙妙趣排序后可以变成即将排好序的序列。
输入
第一行一个正整数t表示数据组数 (0<t<100)
接下来 t 组数据
每组数据第一行两个整数 n,k(2≤n≤50,0≤k≤10)
每组数据接下来k行,每行两个整数u,v,表示一个过滤器 (1≤u<v≤n)
输出
每组数据输出一行,一个整数
输入样例
4
4 0
4 1
1 2
4 3
1 2
2 3
1 2
4 6
1 2
2 3
1 2
3 4
2 3
1 2
输出样例
10
14
24
24
思路
首先考虑一点,任意一个排列,如果排序后可以变成即将排好序的序列,那么他一定对应一个且仅一个即将排好序的序列。多个排列可能对应一个即将排好序的序列。也就是说,这是一个类似于函数多对一的关系。
那么,我们来枚举所有即将排好序的序列,反推其原始排列,这些原始排列一定不会重复。
所以,枚举+dfs即可。注意dfs过程中剪枝验证合法性、
枚举所有即将排好序的序列可以在 O(n2) 内完成,dfs的复杂度大概为 O(2k)
代码
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int ms = 50 + 10;
const int inf = 0x3f3f3f3f;
int t, n, k;
pair<int, int> opt[ms];
int ans;
void dfs(int x, vector<int>& to)
{
if (x == 0)
{
ans++;
return;
}
int u = opt[x].first - 1, v = opt[x].second - 1;
if (to[u] > to[v])return;
dfs(x - 1, to);
swap(to[u], to[v]);
dfs(x - 1, to);
swap(to[u], to[v]);
}
int main()
{
cin >> t;
while (t--)
{
ans = 0;
scanf("%d%d", &n, &k);
for (int i = 1; i <= k; ++i)
{
scanf("%d%d", &opt[i].first, &opt[i].second);
}
vector<int> to(n, 0);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
to[j] = j + 1;
}
for (int j = i; j > 0; --j)
{
swap(to[j], to[j - 1]);
if (i >= 1 && j == i) continue;
dfs(k, to);
}
for (int j = 0; j < i; ++j)
{
swap(to[j], to[j + 1]);
}
for (int j = i; j < n - 1; ++j)
{
swap(to[j], to[j + 1]);
dfs(k, to);
}
}
for (int j = 0; j < n; ++j)
{
to[j] = j + 1;
}
dfs(k, to);
printf("%d\n", ans);
}
return 0;
}
标签:2019E1,++,妙趣,排好序,dfs,int,au,序列,排序 来源: https://blog.csdn.net/weixin_44024733/article/details/102759383
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。