遗迹之门
来源:互联网 发布:adobe cs6 注册机 mac 编辑:程序博客网 时间:2024/06/08 00:10
Description
NightElf 是一个古老的种族,在他们的遗迹上到处都有古NightElf 的奇妙文字,这些文字都是一些十分美妙而复杂的符号。然而,现在的NightElf 人早已不认识古文字了,因为古文字过于复杂,在几十个世纪前,他们就改用简单的英文字母来代替古代的文字符号,每个古文字符号对应一个英文字母。当然,正是因为对应关系渐渐被人遗忘、,所以古代文字已经无法阅读。除了这一点之外,古语同现代语没有任何区别。有一天,探险家Arthas 在一个古老的NightElf 遗迹前面被一扇门给拦住了。大门上用NightElf 文字刻着一句话。当地人告诉他,只有知道这句话的意思,解出一个谜题,才能进入这个遗迹。
于是 Arthas 下决心要找出古文字和现代的英文字母之间的联系,理解这句话的含义。然而这并不是一件轻松的工作。所辛,他的一个朋友是语言学家,告诉他一些很重要的事实:NightElf 文字共有n(1<=n<=27)个文字符号。其中n-1 个文字是有意义的,这n-1 个文字在现代语中用小写字母a,b,…中的前 n-1 个表示。还有一个文字是分隔符。
在句子中每个单词之间有且仅有一个分隔符,将单词隔开。另外NightElf 语言中的合法单词有着非常丰富的意义。因此只有很少的单词。当然,遗迹之门上的那一句话的每个单词都应该是NightElf 语言中的合法单词。于是Arthas想通过了解NightElf 语言中的所有单词,来试着找出句子的含义。
Input
第一行一个整数 t,表示有t 组测试数据。
每组数据第一行是两个整数n(1<=n<=27)和m(1<=m<=150),分别表示NightElf 语言的字符数和句子的字符数。
接着一行有 m 个整数,每个整数都在1 到n 之间,且1 到n 中的每一个数都会出现。每个数代表一个古NightElf 语言的文字符号,相同的数字表示相同的文字符号。
再接下来一个整数q(1<=q<=200),表示NightElf 语言的单词数。
接下来有 q 行,每行一个有现代语写出的(即用小写字母表示)单词。每个单词的长度不超过10。
Output
输出一行,是 Arthas 对输入古文的分析结果:
1)如果句子只有惟一的可能,将它翻译成现代语输出;
2)如果没有任何可能的单词组合组成句子,输出No solution;
3)如果句子有多种可能的组合,输出Cannot determine。
Sample Input
1
5 18
3 2 1 3 5 4 2 1 1 5 2 4 3 4 5 3 4 1
14
adca
bacb
cacc
adba
cabb
bdcc
dacc
baaa
dbab
acbc
daba
cba
abc
dcb
Sample Output
adca bdcc dbab abc
Hint
40%的数据满足: t=1,n<=6,m<=30,q<=40
100%的数据满足: t<=3,n<=27,m<=150,q<=200
【分析】
寻找集合{1,2,…}与集合{’a’,’b’,…}的一一对应关系,实质是一个排列生成问题。
Step1:确定分隔符(空格),需要穷举每个数字能否作为空格,原则是:一旦确定i是空格,则特殊的语言中分出来形成单词的长度要在单词表中出现才行。这可以排除显然无解的情况:例如样例中,以1作为空格,则第一个单词为3 2,而单词表中没有长度为2的单词。
Step2:搜索对应关系:
搜索策略1:用排列搜索出一种对应关系,再判断是否合法,时间复杂度O(n!)
搜索策略2:按照给出的特殊语言a[1]..a[m]的顺序进行搜索对应关系,这样的搜索顺序为我们剪枝提供了方便:
剪枝:搜索单词的时候,用一个数组建立对应关系,若发现当前字母与之前的对应关系有冲突,剪枝。
这个剪枝相当强,只需这个剪枝便可以100ms左右过了。
【代码】
#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<ctime>#include<iostream>#include<algorithm>using namespace std;int T,N,M,Nt,ANS,v[300],Q;string w[300],s;char match[30],path[30]; //path数组记录答案bool f[30];int ans;void _DFS(int k){ if(k>M) { memcpy(path,match,sizeof(match)); ans++; ANS=N; //记录取得答案的分隔符 return; } bool ft[30]; char mt[30]; memcpy(ft,f,sizeof(f)); memcpy(mt,match,sizeof(match)); for(int i=1;i<=Q;i++) { memcpy(f,ft,sizeof(ft)); memcpy(match,mt,sizeof(mt)); int j,p=1; for(j=k;v[j]!=N&&j<=M;j++); j--; if((j+1-k)!=w[i].length()) continue; for(int o=k;o<=j;o++) { int oi=o+1-k; //剪枝 if((('a'<=match[v[o]]&&match[v[o]]<='z')||(f[w[i][oi-1]-'a']==true))&&match[v[o]]!=w[i][oi-1]) { p=0; break; } match[v[o]]=w[i][oi-1]; f[w[i][oi-1]-'a']=true; } if(p==0) continue; _DFS(j+2); if(ans>=2) return; } }void _init(){ ans=0; memset(path,0,sizeof(path)); //注意初始化数组 memset(v,0,sizeof(v)); scanf("%d%d",&N,&M); for(int i=1;i<=M;i++) scanf("%d",&v[i]); scanf("%d",&Q); for(int i=1;i<=Q;i++) cin>>w[i]; Nt=N;}void _solve(){ for(N=1;N<=Nt;N++) //枚举哪个数字作为分隔符 { for(int i=1;i<=Q;i++) { int j,p=1; memset(match,0,sizeof(match)); memset(f,0,sizeof(f)); for(j=1;v[j]!=N;j++); j--; if(j!=w[i].length()) continue; for(int o=1;o<=j;o++) { if((('a'<=match[v[o]]&&match[v[o]]<='z')||(f[w[i][o-1]-'a']==true))&&match[v[o]]!=w[i][o-1]) { p=0; break; } match[v[o]]=w[i][o-1]; f[w[i][o-1]-'a']=true; } if(p==0) continue; _DFS(j+2); if(ans>=2) { printf("Cannot determine\n"); return; } } } if(ans) { for(int i=1;i<=M;i++) { if(v[i]==ANS) printf(" "); else if('a'<=path[v[i]]&&path[v[i]]<='z') printf("%c",path[v[i]]); } printf("\n"); } else printf("No solution\n");}int main(){ scanf("%d",&T); for(int i=1;i<=T;i++) { _init(); _solve(); } return 0;}
- 遗迹之门
- Sicily 1213. 打开遗迹之门
- 品千秋之遗迹, 叹万世之须臾
- 遗迹系列
- 下载和攻略补遗之人偶遗迹 ひとがたルイン
- 秘籍和修改器之人偶遗迹 ひとがたルイン
- 寻找南京历史遗迹
- 同一个世界 四维离殇 遗迹 攻略
- [NOIP2010冲刺十三] 逃离遗迹
- [软件人生]历史的遗迹与放下
- 东北年俗中的萨满遗迹
- 同一个世界 三生梦醒 遗迹 攻略
- 2008/10/01 长乐郑和遗迹探寻
- 【最短路】逃离遗迹 escape.pas/c/cpp
- 游戏 SNRS超新星遗迹 Alpha测试版发布
- 修改navigationBar上的title的字体遗迹大小
- 遗迹系列 -【学渣告诉你】到底神马是傅里叶级数!
- 广宇进入大雷音寺寻找沃美遗迹
- 网站开发常用jQuery插件总结(四)验证插件validation
- 取消 “是否把IE8设置为默认浏览器提示" 提示
- oracle常用命令
- 网络子系统11_arp子系统初始化
- ADF页面重定向
- 遗迹之门
- A. Cinema Line
- 基本的三维旋转
- ADF: ADF Task Flow学习--part1
- iOS 7
- sparse representation
- C + +0 x中:C + +的未来
- 如何将excel导入到oracle数据库中
- ADF: ADF Task Flow学习--part2