传话游戏
时间限制: 1000ms 内存限制: 256MB
描述
Alice和Bob还有其他几位好朋友在一起玩传话游戏。这个游戏是这样进行的:首先,所有游戏者按顺序站成一排,Alice站第一位,Bob站最后一位。然后,Alice想一句话悄悄告诉第二位游戏者,第二位游戏者又悄悄地告诉第三位,第三位又告诉第四位……以此类推,直到倒数第二位告诉Bob。两位游戏者在传话中,不能让其他人听到,也不能使用肢体动作来解释。最后,Bob把他所听到的话告诉大家,Alice也把她原本所想的话告诉大家。
由于传话过程中可能出现一些偏差,游戏者越多,Bob最后听到的话就与Alice所想的越不同。Bob听到的话往往会变成一些很搞笑的东西,所以大家玩得乐此不疲。经过几轮游戏后,Alice注意到在两人传话中,有些词汇往往会错误地变成其他特定的词汇。Alice已经收集到了这样的一个词汇转化的列表,她想知道她的话传到Bob时会变成什么样子,请你写个程序来帮助她。
输入
输入包括多组数据。第一行是整数 T,表示有多少组测试数据。每组数据第一行包括两个整数 N 和 M,分别表示游戏者的数量和单词转化列表长度。随后有 M 行,每行包含两个用空格隔开的单词 a 和 b,表示单词 a 在传话中一定会变成 b。输入数据保证没有重复的 a。最后一行包含若干个用单个空格隔开的单词,表示Alice所想的句子,句子总长不超过100个字符。所有单词都只包含小写字母,并且长度不超过20,同一个单词的不同时态被认为是不同的单词。你可以假定不在列表中的单词永远不会变化。
输出
对于每组测试数据,单独输出一行“Case #c: s”。其中,c 为测试数据编号,s 为Bob所听到的句子。s 的格式与输入数据中Alice所想的句子格式相同。
数据范围
1 ≤ T ≤ 100
小数据:2 ≤ N ≤ 10, 0 ≤ M ≤ 10
大数据:2 ≤ N ≤ 100, 0 ≤ M ≤ 100
样例输入
2
4 3
ship sheep
sinking thinking
thinking sinking
the ship is sinking
10 5
tidy tiny
tiger liar
tired tire
tire bear
liar bear
a tidy tiger is tired
样例输出
Case #1: the sheep is thinking
Case #2: a tiny bear is bear
主算法:
define 输出集合L
get T
for 1 to T
get N,M
for 1 to M-1
get 词对
get 会变词集合
把 变化词集合重构为 循环变化词集 和 传递变化词集合
get 变化语句(words)
for-each word word属于words
if 会 变词集合 contains(word)
依据 循环变化词集 和 传递变化词集合 加上N 对word进行变化
L.add(words)
print L
时间限制: 1000ms 内存限制: 256MB
描述
Alice和Bob还有其他几位好朋友在一起玩传话游戏。这个游戏是这样进行的:首先,所有游戏者按顺序站成一排,Alice站第一位,Bob站最后一位。然后,Alice想一句话悄悄告诉第二位游戏者,第二位游戏者又悄悄地告诉第三位,第三位又告诉第四位……以此类推,直到倒数第二位告诉Bob。两位游戏者在传话中,不能让其他人听到,也不能使用肢体动作来解释。最后,Bob把他所听到的话告诉大家,Alice也把她原本所想的话告诉大家。
由于传话过程中可能出现一些偏差,游戏者越多,Bob最后听到的话就与Alice所想的越不同。Bob听到的话往往会变成一些很搞笑的东西,所以大家玩得乐此不疲。经过几轮游戏后,Alice注意到在两人传话中,有些词汇往往会错误地变成其他特定的词汇。Alice已经收集到了这样的一个词汇转化的列表,她想知道她的话传到Bob时会变成什么样子,请你写个程序来帮助她。
输入
输入包括多组数据。第一行是整数 T,表示有多少组测试数据。每组数据第一行包括两个整数 N 和 M,分别表示游戏者的数量和单词转化列表长度。随后有 M 行,每行包含两个用空格隔开的单词 a 和 b,表示单词 a 在传话中一定会变成 b。输入数据保证没有重复的 a。最后一行包含若干个用单个空格隔开的单词,表示Alice所想的句子,句子总长不超过100个字符。所有单词都只包含小写字母,并且长度不超过20,同一个单词的不同时态被认为是不同的单词。你可以假定不在列表中的单词永远不会变化。
输出
对于每组测试数据,单独输出一行“Case #c: s”。其中,c 为测试数据编号,s 为Bob所听到的句子。s 的格式与输入数据中Alice所想的句子格式相同。
数据范围
1 ≤ T ≤ 100
小数据:2 ≤ N ≤ 10, 0 ≤ M ≤ 10
大数据:2 ≤ N ≤ 100, 0 ≤ M ≤ 100
样例输入
2
4 3
ship sheep
sinking thinking
thinking sinking
the ship is sinking
10 5
tidy tiny
tiger liar
tired tire
tire bear
liar bear
a tidy tiger is tired
样例输出
Case #1: the sheep is thinking
Case #2: a tiny bear is bear
主算法:
define 输出集合L
get T
for 1 to T
get N,M
for 1 to M-1
get 词对
get 会变词集合
把 变化词集合重构为 循环变化词集 和 传递变化词集合
get 变化语句(words)
for-each word word属于words
if 会 变词集合 contains(word)
依据 循环变化词集 和 传递变化词集合 加上N 对word进行变化
L.add(words)
print L
代码:
import java.util.*; public class Main { final static int FLAG=-1; public static void main(String[] args){ int T=0; int N=0; int M=0; Scanner sc=new Scanner(System.in); T=Integer.valueOf(sc.nextLine()); String[] list=new String[T]; /*分别对每组数据进行处理*/ for(int i=0;i<T;i++){ String str1=sc.nextLine(); String[] nums=str1.trim().split(" "); N=Integer.valueOf(nums[0]); M=Integer.valueOf(nums[1]); String[][] twoWords=new String[M][2]; for(int j=0;j<M;j++){ String str2=sc.nextLine(); String[] words=str2.trim().split(" "); twoWords[j][0]=words[0];; twoWords[j][1]=words[1]; } // 要交换的词 String[]exWords=getExWords(twoWords); /* 一下全部是基于词下标的处理*/ int[][] twos=getTwos(twoWords,exWords); /*处理集合,circulate是循环体,transmit是传递体,要是传递体的最后一个元素是-1,那么它是一个复合体*/ List<List<Integer>> circulate=new ArrayList<List<Integer>>(11); List<List<Integer>> transmit=new ArrayList<List<Integer>>(11); /* 为处理集合赋值*/ handleWords(circulate,transmit,twos,exWords); /* 处理集合所包含的词集*/ int[] wordsC=getWordSet(circulate); int[] wordsT=getWordSet(transmit); String sentence=sc.nextLine(); String[] words=sentence.split(" "); /*对词进行处理*/ for(int j=0;j<words.length;j++){ int temp=getIndex(words[j],exWords); //把要处理的词变化为可处理词集的编号,要是-1则不处理 if(words[j].length()>0 && temp!=-1){ if(!disContains(temp,wordsC)){ /* 要处理的词在循环体词集中*/ swap(words,j,circulate,N,exWords); }else if(!disContains(temp,wordsT)){ /* 要处理的词在传递体词集中*/ swap(words,j,circulate,transmit,N,exWords); } } } /*对处理后的词继续合并*/ String temp=""; for(String word:words){ temp=temp+" "+word; } /* 处理结果合并*/ list[i]=temp.trim(); } /*打印处理结果*/ printResult(list); } /*集合中包含的不同词集*/ private static int[] getWordSet(List<List<Integer>> lists) { ArrayList<Integer> temp=new ArrayList<Integer>(11); for(List<Integer> list:lists){ for(int x:list){ if(!temp.contains(x)) temp.add(x); } } int[] xs=new int[temp.size()]; for(int i=0;i<xs.length;i++){ xs[i]=temp.get(i); } return xs; } /*把变化词对进行编号化处理*/ private static int[][] getTwos(String[][] twoWords, String[] exWords) { int[][] temp=new int[twoWords.length][2]; for(int i=0;i<twoWords.length;i++){ for(int j=0;j<2;j++){ temp[i][j]=getIndex(twoWords[i][j],exWords); } } return temp; } /*把单个词语编号化*/ private static int getIndex(String str, String[] exWords) { int temp=-1; for(int i=0;i<exWords.length;i++){ if(str.equals(exWords[i])) return i; } return temp; } /*得到可编号化的集合*/ private static String[] getExWords(String[][] twos) { ArrayList<String> temp=new ArrayList<String>(10); for(String[] words:twos) for(String word:words) if(!temp.contains(word)) temp.add(word); String[] exWords=new String[temp.size()]; for(int i=0;i<temp.size();i++) exWords[i]=temp.get(i); return exWords; } /*打印结果集*/ private static void printResult(String[] list) { for(int i=0;i<list.length;i++) System.out.println("Case #"+(i+1)+":"+list[i]); } /*有循环体参与的句子中词语处理*/ private static void swap(String[] words, int j, List<List<Integer>> listC, int n,String[] exWords) { String temp=words[j]; int intTemp=getIndex(temp,exWords); for(List<Integer> list:listC){ if(list.contains(intTemp)){ int index=list.indexOf(intTemp); int size=list.size(); int step=n-1; words[j]=exWords[list.get((index+step)%size)]; return; } } } /*有传递体参与的句子中词语处理*/ private static void swap(String[] words, int j, List<List<Integer>> listC,List<List<Integer>> listT, int n, String[] exWords) { String temp=words[j]; int intTemp=getIndex(temp,exWords); for(List<Integer> list:listT){ if(list.contains(intTemp)){ int index=list.indexOf(intTemp); int size=list.size(); int step=n-1; if(index+step<size-1) words[j]=exWords[list.get(index+step)]; else{ int x=size-2-index; if(list.get(size-1)==FLAG){ words[j]=exWords[list.get(size-2)]; swap(words,j,listC,n-x,exWords); }else{ words[j]=exWords[list.get(size-1)]; } } return; } } } /* 为处理集合赋值*/ private static void handleWords(List<List<Integer>> circulate, List<List<Integer>> transmit, int[][] twos, String[] exWords) { int[] keys=get(twos,0); int[] values=get(twos,1); for(int i=0;i<twos.length;i++){ /* 对一个处理链条的第一个词进行处理*/ if(disContains(twos[i][0],values)) handleHead(twos[i][0],twos,circulate,transmit,values); else{ if(test(twos[i][0],twos,keys,values)&&noCir(circulate,twos[i][0])) handleHead(twos[i][0],twos,circulate,transmit,values); } } } private static boolean noCir(List<List<Integer>> lists, int k) { for(List<Integer> list:lists){ if(list.contains(k)) return false; } return true; } private static boolean test(int k, int[][] twos,int[] keys, int[] values) { int x=-10; int temp=k; int value=getValue(temp,twos); if(value==-1) return false; while((!disContains(value,keys))&&(x<twos.length)){ value=getValue(temp,twos); x++; } if(x==twos.length) return true; return false; } /*词组不包含某词编号*/ private static boolean disContains(int k, int[] values) { for(int i=0;i<values.length;i++){ if(k==values[i]) return false; } return true; } /*得到变换词对的某一集合*/ private static int[] get(int[][] twos, int k) { ArrayList<Integer> temp=new ArrayList<Integer>(11); for(int i=0;i<twos.length;i++){ if(!temp.contains(twos[i][k])) temp.add(twos[i][k]); } int[] intTemp=new int[temp.size()]; for(int i=0;i<intTemp.length;i++) intTemp[i]=temp.get(i); return intTemp; } /*对于某一个处理链条的词进行分类*/ private static void handleHead(int head, int[][] two, List<List<Integer>> circulate, List<List<Integer>> transmit, int[] values) { List<Integer> temp=new ArrayList<Integer>(11); temp.add(head); int value=getValue(head,two); while((!temp.contains(value))&&(value!=-1)){ temp.add(value); value=getValue(value,two); } if(value==-1){ transmit.add(temp); }else{ handle(circulate,transmit,temp,value); } } /* 对于某一个词,得到其变换后的词*/ private static int getValue(int head, int[][] two) { int temp=-1; for(int i=0;i<two.length;i++){ if(head==two[i][0]) temp=two[i][1]; } return temp; } /*处理包含循环的集合链条*/ private static void handle(List<List<Integer>> circulate, List<List<Integer>> transmit, List<Integer> temp,int value) { if(temp.indexOf(value)==0){ circulate.add(temp); }else{ handleCir(circulate,value,temp); temp.add(FLAG); transmit.add(temp); } } /*处理单纯循环体*/ private static void handleCir(List<List<Integer>> circulate, int value, List<Integer> temp) { if(noCir(circulate,value)){ return; } int index=temp.indexOf(value); List<Integer> list=new ArrayList<Integer>(11); for(int i=index;i<temp.size();i++){ list.add(temp.get(i)); } circulate.add(list); } }
这是通过了小数据测试的,大数据是否能通过就不知道了。
——20130409
PS:
今天早晨数据出来了,这道题的大数据测试是三个题中唯一的一个AC。在意料之外,以为要是能AC一题也是长方形那个题。但,结果也不错。
——20130409