题目名称 | 945. [東方S3] 稗田阿求 |
---|---|
输入输出 | akyuu.in/out |
难度等级 | ★ |
时间限制 | 1000 ms (1 s) |
内存限制 | 128 MiB |
测试数据 | 10 |
题目来源 | Makazeu 于2012-07-20加入 |
开放分组 | 全部用户 |
提交状态 | |
分类标签 | |
分享题解 |
通过:6, 提交:37, 通过率:16.22% | ||||
水中音 | 100 | 0.004 s | 0.32 MiB | C++ |
不知云 | 100 | 0.005 s | 0.30 MiB | C++ |
Ezoi_XY | 100 | 0.034 s | 0.31 MiB | C++ |
Ezoi_XY | 100 | 0.035 s | 0.31 MiB | C++ |
leeson | 100 | 0.037 s | 0.26 MiB | C++ |
Luckyblock | 100 | 0.232 s | 4.42 MiB | C++ |
Luckyblock | 90 | 0.167 s | 4.41 MiB | C++ |
Luckyblock | 90 | 0.203 s | 4.42 MiB | C++ |
Luckyblock | 90 | 0.247 s | 4.41 MiB | C++ |
Luckyblock | 90 | 0.290 s | 4.41 MiB | C++ |
本题关联比赛 | |||
东方幻想乡 S3 |
关于 稗田阿求 的近10条评论(全部评论) | ||||
---|---|---|---|---|
搬一下官方题解
题目大意 给定 N 个数字, N 个字母。要求确定数字与字母的对应关系,使给定 M 个数字串和字符串组尽可能多的满足对应关系。 考察算法 搜索 位运算/状态压缩 算法一 枚举每个数字对应的字符,时间复杂度 O(N!)。然后通过 O(ML)的时间判断每个字符串数组是否匹配。不断更新最大值。伪代码: DFS(dep) If dep == N Then Num ← Count() If Num > Max Max ← Num End If End If For i = 1 .. N If not used[i] Then used[i] ← true a[dep] ← i DFS(dep + 1) used[i] ← false End If End For 其中 dep 表示枚举到的第几个字符, a[i]表示第 i 个字符对应的数字。 时间复杂度: O(N!•ML) 期望得分: 30 算法二 在算法一的基础上加上简单的剪枝,如果当前数量已经小于已知最大值,就把当前纸 条剪掉。 DFS(dep) Num ← Count() If Num <= Max Then Exit If dep == N Then If Num > Max Max ← Num End If End If For i = 1 .. N If not used[i] Then used[i] ← true a[dep] ← i DFS(dep + 1) used[i] ← false a[dep] ← 0 End If End For 时间复杂度: O(N!•ML) 期望得分: 60 算法三 此算法需要用到一点位运算的知识,阅读前请保证你已经熟练地使用位运算,否则请到 Matrix67 的 Blog 查看相关知识后再进行阅读。 通过题目数据我们可以知道 M 最大不会超过 60,而一个 long long的范围最大到 2^63-1,所以我们可以通过一个 2 进制数来表示当前字符数列组的匹配情况。 1 表示可能匹配, 0 表示不能匹配。同样需要通过全排列来枚举每个字符对应的数字,采用 DFS(dep, rest), rest 表示当前的匹配情况状态。每次枚举一个字符所对应的数字,我们可以通过 O(1)的时间从当前状态中减去不能匹配的状态。建立数组del[i][j]表示当字母 i 对应数字 j 时,会造成那些不能匹配,比如 del[i][j]=(1001)2,表示当字母 i 对应字母 j 时,第 1、 4 字符数列组不能匹配。那么新的状态就等于 new = rest & (~del[i][j])或 new :=rest and (not del[i][j])。 然后再加上算法二的剪枝,就能够通过所有的数据。 接下来考虑如何求出 del[i][j],依次枚举每一个字符数列组,设第 i 个字符数列组对应的 2 进制位置为 t[i]。如果在该字符数组中字母 ch 对应了数字 num,那么其他数字的 del[i][num]和 ch 对应的其他数字 del[ch][j]都应该加上 t[i]。预处理的时间复杂度为 O(MLN^2)。 最后只需要在主函数内调用 DFS(0, (1<<M)-1)即可。 时间复杂度: O(MLN+N!)/O(ML+MN^2+N!) 期望得分: 80 算法四 在算法三的基础上优化搜索顺序,记录每个字母出现的次数,按照最小到大的顺序进行搜索。由于先出现字母影响较小,可以使最后产生的结果尽可能大,很多冗余都会被剪掉。 时间复杂度: O(MLN+N!)/O(ML+MN^2+N!) 期望得分: 100 | ||||
第⑨个点略坑爹,set判重也是醉了
| ||||
贪心骗分拿70,正解……看不懂…………
|
Problem 4 |
稗田阿求(akyuu.cpp/c/pas) |
题目描述 |
在幻想乡,稗田乙女是负责书写《幻想乡缘起》的家族。由于需要代代相传关于幻想乡的记忆,稗田乙女采用了一些特殊的记录方式。对于相同重复的文字,稗田乙女会用一个数字来代替,然后用一个数列来表示一个段文字。比如1代表"A",2代表"C",那么{1,2}就代表"AC",{2,1,2}就代表"CAC"。不过由于年代过于久远,到稗田阿求(ひえだの あきゅう)时已经是第九代稗田乙女,所以难免会出现错误。现在阿求有N个数字(1..N)和N个字符('A'..第N个字母),以及一些以前传承下来的M组文字段和对应的数列。每一组文字段和数列相互对应,文字的第i个字符对应着数列的第i项。阿求想要知道怎样安排N个数字和字符的对应关系,能够使组数尽可能多的文字段和数列组合满足该对应关系。数字和字符间一一对应,不会出现多对一或一对多的情况。 |
输入格式 |
第1行:2个正整数N, M 第2..2*M+1行:每2行为一组,第1行为文字段落,第2行为数列。保证文字段落的字符数L等于数列数字个数L,且均在1..N。文字段落只包含大写字母 |
输出格式 |
第1行:最多能够匹配的文字段落和数列组合数量 |
输入样例 |
3 3 ACCA 1 3 3 1 AAC 2 2 1 BCBC 3 1 3 1 |
输出样例 |
2 |
样例解释 |
当A=2,B=3,C=1时第2、3字符串和数列组合满足对应关系。 |
数据范围 |
对于60%的数据: 1 ≤ N ≤ 10,1 ≤ M ≤ 20 对于100%的数据:1 ≤ N ≤ 26,1 ≤ M ≤ 60 对于100%的数据:1 ≤ L ≤ 100 |
注意 |
保证每一组文字段和数列组合均合法; 在一组文字段和数列组合里面不会出现多个字符对一个数字,或是一个字符对多个数字的情况。 |