HDOJ-ACM1015(JAVA) 运用 组合、全排列实现

时间:2023-03-09 19:22:33
HDOJ-ACM1015(JAVA) 运用 组合、全排列实现

转载声明:原文转自:http://www.cnblogs.com/xiezie/p/5573934.html

HDOJ-ACM1015(JAVA) 运用 组合、全排列实现

这个题目的题意:(自己结合百度翻译,简单的翻译了一下)

“这个项目是在一个在二楼图书馆一幅画的背后的克莱因的保险箱里。克莱因的保险柜是极为罕见的;他们中的大多数都随着克莱因和他的工厂在二战中被摧毁。幸运的是,老布伦博在他死之前研究发现了克莱因的秘密并写下来了。一个克莱因保险箱有两个特点是:一个使用字母而不是数字的组合锁,和一个刻在门上的引用。克莱因的引用总是包含五个和十二个不同的大写字母之间,通常在句首,并提到了一个或多个数字。五种大写字母的形成了打开保险柜的密码。通过把所有的数字与适当的方式相结合,你将得到一个数字目标。(构造目标密码的细节)要找到组合,你必须选择五个字母,v, w, x, y, 和 z 并满足下面的方程,其中每一个字母被替换的顺序位置在字母组中(a= 1,b= 2,…,z= 26)。组合是vwxyz。如果有一个以上的解决方案则选择字典最大的组合,即,组合会出现在字典上的最后一个。”

v - w^2 + x^3 - y^4 + z^5 = target

例如,给定的目标1和字母abcdefghijkl,一个可能的解决方案是fiecb,6 - 9 ^ 2 + 5 ^ 3 - 3 ^ 4 + 2 ^ 5 = 1。其实在这种情况下的几种解决方案,但最终组合是lkeba。克莱因认为雕刻的编码组合是安全的,因为它可能需要几个月的努力,尝试所有的可能性,即使你知道这个秘密。当然,电脑那时不存在了。”

“开发一个程序,以寻找克莱因组合,以准备现场部署。按部门规定使用标准测试方法。输入包含一个或多个包含一个正整数目标低于一千二百万,并且至少五个最多十二个不同的大写字母。最后一行将包含一个零和字母的组合码 END 意味着输入结束。每行输出的克莱因组合是乱序的,如果没有正确的组合输出'no solution'。使用下面显示的精确格式。”

简单的题意是:

  从输入的字符串中,找出五个字母代替v、w、x、y、z,符合v - w^2 + x^3 - y^4 + z^5 = target 的所有答案中,输出最大的字符串。

我是思路是:获取长度为5的组合数,进行全排列并判断是否符合目标函数。

  因为做这道题,我把全组合和全排列算法实现了一遍。http://www.cnblogs.com/xiezie/p/5574516.html

注意:我偷了个懒,这道题我下面的代码可以优化,不过思路一样。

  可以不将结果存储起来,只需要实现字典序全排列,输出最后一个结果即可(将结果保存起来用字符串保存起来,一旦遇到下一个合适的字符串则替换)

以下是java实现:

import java.util.*;

import java.io.*;

public class Main1015{

    public static void main(String[] arg){
Scanner scan = new Scanner(new BufferedInputStream(System.in));
int target;
String inputStr;
ArrayList<String> answers = new ArrayList<>();
ArrayList<String> combinations = new ArrayList<>();
ArrayList<Character> com = new ArrayList<>(5);
while(true){
target = scan.nextInt();
inputStr = scan.next();
if(target ==0 && inputStr.contentEquals("END")){
break;
}
answers.clear();
combinations.clear();
com.clear();
//获取所有的组合
getCombinations(combinations,inputStr.toCharArray(),0,5,com);
//获取全排列
for(int i = 0 ; i != combinations.size() ; i ++ ){
ArrayList<String> permutations = new ArrayList<>();
getAllPermutations(permutations,combinations.get(i).toCharArray(),0,combinations.get(i).length());
//判断是否符合target函数,符合则放入answer
for(int j = 0 ; j != permutations.size() ; j ++){
if(target(permutations.get(j), target)){
answers.add(permutations.get(j));
}
}
} String answerCode = "" ;
for(int i = 0 ; i != answers.size() ; i ++ ){
if(answers.get(i).compareTo(answerCode)>=1){
answerCode = answers.get(i);
}
}
if(answerCode.equals("")){
System.out.println("no solution");
}else{
System.out.println(answerCode);
}
}
scan.close();
} static boolean target(String s,int target){
char[] cs = s.toCharArray();
return (cs[0]-'A'+1)-Math.pow(cs[1]-'A'+1,2)+Math.pow(cs[2]-'A'+1,3)-Math.pow(cs[3]-'A'+1,4)+Math.pow(cs[4]-'A'+1,5)==target;
} static void getAllPermutations(ArrayList<String> answers,char[] cs,int start,int len){
if(start == len ){
answers.add(String.valueOf(cs));
return;
}
for(int i = start ; i != len ; i ++){
swap(cs,i,start);
getAllPermutations(answers,cs,start+1,len);
swap(cs,i,start);
}
} static void getCombinations(ArrayList<String> list ,char[] cs, int start,int len,ArrayList<Character> com){//len为组合的长度
if(len == 0){
String s = "";
for(int i = 0 ; i != com.size() ; i ++){
s = s.concat(com.get(i).toString());
}
list.add(s);
return;
}
if(start==cs.length){
return;
}
com.add(cs[start]);
getCombinations(list,cs,start+1,len-1,com);
com.remove(com.size()-1);
getCombinations(list,cs,start+1,len,com);
} static void swap(char[] cs , int i , int j){
char t;
t = cs[i];
cs[i] = cs[j];
cs[j] = t;
}
}