昂。本来上一次是写到这儿的。可是后来写完分析就没时间 了。然后接着写。。
第一部分肯定是遍历了。因为是统计正确解的问题,第二部分是如何化简分数,其实 不用,因为这道题的精度并不高,分数就是除法运算。我们把结果算出来一比较就好了。第三就是排除重复的答案。也不难。用位图法都可以。
第一步 先把所有情况用算法表示出来
如果真的全用循环来算的话。恐怕需要四层这样效率很低。所以我们用空间来换时间
private static int getresult(double start, double end) {
// TODO Auto-generated method stub
int result = 0;
for (double i = start; i <= end; i++) {
for (double j = start; j <= end; j++) {
System.out.println(i + "/" + j+"="+(i / j));
}
}
return result;
}
结果
..................
这样就先把所有数都列出来 了。然后存储到一个临时数组里。然后对数组进行操作。
第二步写出判断语句
private static int getresult(int start, int end) {
// TODO Auto-generated method stub
int result = 0;
String temp[] = new String[(end * end)];
int index = 0;
for (int i = start; i <= end; i++) {
for (int j = start; j <= end; j++) {
temp[index] = i + "/" + j;
index++;
}
}
for (int i = 0; i < temp.length; i++) {
for (int j = i; j < temp.length; j++) {
if (temp[i].split("/")[0].equals(temp[i].split("/")[1])
&& temp[j].split("/")[0].equals(temp[j].split("/")[1])) {
continue;
}
System.out.print(temp[i].split("/")[0] + "*"
+ temp[j].split("/")[0] + "/" + temp[i].split("/")[1]
+ "/" + temp[j].split("/")[1] + "?=");
System.out
.println((10 * dou(temp[i].split("/")[0]) + dou(temp[j]
.split("/")[0]))
+ "/"
+ ((10 * dou(temp[i].split("/")[1]) + dou(temp[j]
.split("/")[1]))));
if (dou(temp[i].split("/")[0]) * dou(temp[j].split("/")[0])
/ dou(temp[i].split("/")[1])
/ dou(temp[j].split("/")[1]) == (10 * dou(temp[i]
.split("/")[0]))
+ dou(temp[j].split("/")[0])
/ ((10 * dou(temp[i].split("/")[1]) + dou(temp[j]
.split("/")[1])))) {
System.out.println(temp[i] + " " + temp[j]);
}
}
}
return result;
}
public static double dou(String a) {
return Double.parseDouble(a);
}
1*1/1/2?=11.0/12.0 把所有的等式情况都列出来
1*1/1/3?=11.0/13.0
1*1/1/4?=11.0/14.0
1*1/1/5?=11.0/15.0
1*1/1/6?=11.0/16.0
1*1/1/7?=11.0/17.0
1*1/1/8?=11.0/18.0
1*1/1/9?=11.0/19.0
1*2/1/1?=12.0/11.0
1*2/1/3?=12.0/13.0
1*2/1/4?=12.0/14.0
1*2/1/5?=12.0/15.0
1*2/1/6?=12.0/16.0
.........
这时候 就看出代码可读性的重要了。。根本无法调试。。所以要做一下可读性的整理
private static int getresult(int start, int end) {
// TODO Auto-generated method stub
int result = 0;
String temp[] = new String[(end * end)];
int index = 0;
for (int i = start; i <= end; i++) {
for (int j = start; j <= end; j++) {
temp[index] = i + "/" + j;
index++;
}
}
for (int i = 0; i < temp.length; i++) {
for (int j = i; j < temp.length; j++) {
double a = dou(temp[i].split("/")[0]);
double b = dou(temp[i].split("/")[1]);
double c = dou(temp[j].split("/")[0]);
double d = dou(temp[j].split("/")[1]);
if (a == b && c == d) {
continue;
}
// System.out.println(a + "/" + b +" "+ c + "/" +
// d);
// System.out.println(a / b * c / d);
// System.out.println(((10 * a) + c) / ((10 * b) + d));
if (a / b * c / d == ((10 * a) + c) / ((10 * b) + d)) {
System.out.println((int) a + "/" + (int) b + " "
+ (int) c + "/" + (int) d);
}
}
}
return result;
}
public static double dou(String a) {
return Double.parseDouble(a);
}
结果:
1/2 5/4
1/4 8/5
1/6 4/3
1/6 6/4
1/9 9/5
2/1 4/5
2/6 6/5
4/1 5/8
4/9 9/8
结果为奇数。不合题意。。看结果并不是对称的。这样就很可能是没有循环到那个情况
整理一下结果
1/2 5/4 === 2/1 4/5
1/4 8/5===4/1 5/8
1/6 4/3===?6/1 3/4 这个是否未循环到看一下输出。
1/6 6/4===?
把for循环里边j==i改成了j==0本来以为用前一种可 以避免重复。。没想到弄巧成拙了结果2:
1/2 5/4
1/4 8/5
1/6 4/3
1/6 6/4
1/9 9/5
2/1 4/5
2/6 6/5
4/1 5/8
4/9 9/8
6/1 3/4
6/1 4/6
6/2 5/6
9/1 5/9
9/4 8/9
这回对了。。
• 7. 扑克序列
AA223344, 一共4对扑克牌。请你把它们排成一行。
要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌。
4A3A2432
2342A3A4
请填写出所有符合要求的排列中,字典序最小的那个。
例如:22AA3344 比 A2A23344 字典序小。当然,它们都不是满足要求的答案。
2342A3A4
请通过浏览器提交答案。“A”一定不要用小写字母a,也不要用“1”代替。字符间一定不要留空格。
这题的难点 是如何列出所有的结果,第一种方法 按规则罗列结果显然有些难。第二种就是罗列所有结果找出符合规则的组。
应该是排列组合里边的A几几
那么现在的问题就变成了如何用算法实现A排列组合
平常思维 是
从8个里挑一个放到第一个。
那么要想实现遍历。就是挑8个各放在第一组。这里有4个是重复的。所以挑4个
第二步从剩下的7个里再遍历放在第二个。
private static int getresult(int start, int end) {
// TODO Auto-generated method stub
int result = 0;
char[] temp = { 'A', 'A', '2', '2', '3', '3', '4', '4' };
StringBuilder t = new StringBuilder();
int [] intt=new int[8];
for (int i = 0; i < temp.length; i++) {
t.append(temp[i]);
intt[0]=i;
for (int j = 0; j < temp.length; j++) {
if (intt[0]==j) {
continue;
}
t.append(temp[j]);
intt[1]=j;
for (int j2 = 0; j2 < temp.length; j2++) {
if (intt[0]==j2||intt[1]==j2) {
continue;
}
t.append(temp[j]);
intt[1]=j;
for (int k = 0; k < intt.length; k++) {
.............
}
}
}
}
return result;
}
用这种方式虽然能实现,但是代码长不好读也不美观。不过也许在比赛中没时间想别的那就只能这种了
上边这种方法特别像递归。所以我们试试用递归实现
private static int getresult(int start, int end) {
// TODO Auto-generated method stub
int result = 0;
char[] temp = { 'A', 'A', '2', '2', '3', '3', '4', '4' };
StringBuilder t = new StringBuilder();
int[] intt = new int[8];
for (int i = 0; i < temp.length; i++) {
append(t, intt, temp, 0);
}
return result;
}
private static void append(StringBuilder t, int[] intt, char[] temp,
int index) {
// TODO Auto-generated method stub
if (index ==7) {
System.out.println(t);
}
for (int i = 0; i < temp.length; i++) {
if (isok(intt, i))
t.append(temp[i]);
else
continue;
if (index > 7) {
index = 7;
} else
index++;
intt[index] = i;
append(t, intt, temp, index);
}
}
private static boolean isok(int[] intt, int i) {
// TODO Auto-generated method stub
for (int c : intt) {
if (i == c) {
return false;
}
}
return true;
}
本来打算用递归实现 ,后来发现递归其实上是深度优先的。这样就造成了不可循环性。因为intt做为存放已用字符的下标载体将会再第一次递归完成后充满。那么也就是说每次递归完成后都要将这个数组清空才行?或者是退格一个字符。
其实 刚才 想这个的时候 我已经想到其实 不必排字符了。直接把下标做个A排列就好了。明天再更