蓝桥杯-神奇算式

1441434079

摘要:本题是2014年第五届蓝桥杯全国软件大赛预赛A组第3题。
题目描述

标题:神奇算式
由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成。
比如:
210 x 6 = 1260
8 x 473 = 3784
27 x 81 = 2187
都符合要求。
如果满足乘法交换律的算式算作同一种情况,那么,包含上边已列出的3种情况,一共有多少种满足要求的算式。
请填写该数字,通过浏览器提交答案,不要填写多余内容(例如:列出所有算式)。
解题思路

对于这道题目我使用的遍历,加控制条件减少遍历次数
两个明显的限制条件:
1.每个数字的每一位数字不允许重复;
2.算式左边个数字跟右边的相等。
我的解题思路是从结果开始遍历,先判断限制条件一,
然后再通过结果这个数的数字构造出1位数的2位数的,
接着再用结果除以这个数来判断是否符合。
巧用Java集合类排序
运行时间0.165s左右,还算乐观。

之后百度发现用枚举法是不错的选择,对每个数出现的数字进行标记
代码实现

package lanqiaobei;

import java.util.HashSet;
import java.util.TreeSet;

/**

  • @author Ape
  • @date 2015-9-5
  • /

public class SuanShi {

private static TreeSet< Integer> set = new TreeSet<>();

/**
 * 递归排序结果,并拿到1位数和2位数的排序放到set集合,三位数的没必要拿到,因为一除就可以得到那个三位数或者两位数
 * @param s1
 * @param s2
 */
public static void put(StringBuilder s1, StringBuilder s2) {
    if (s2.length() == 1 || s2.length() == 2)
        set.add(Integer.parseInt(s2.toString()));
    for (int i = 0; i < s1.length(); i++) put(new StringBuilder(s1).deleteCharAt(i), new StringBuilder(s2).append(s1.charAt(i))); } /** * 判断是否符合不重复数字的4位数 * @param i * @return */ public static boolean isNum(int i) { HashSet< Integer> set = new HashSet<>();
    while (i > 0) {
        set.add(i % 10);
        i = i / 10;
    }
    if (set.size() == 4)
        return true;
    else
        return false;
}

/**
 * 判断两个数的数字跟结果是否相同
 * @param i
 * @param k
 * @param j
 * @return
 */
public static boolean isNum(int i, int k, int j) {
    TreeSet< Integer> set1 = new TreeSet();
    TreeSet< Integer> set2 = new TreeSet();
    int n = 0;
    while (i > 0) {
        set1.add(i % 10);
        i = i / 10;
    }
    while (j > 0) {
        set2.add(j % 10);
        j = j / 10;
        n++;
    }
    while (k > 0) {
        set2.add(k % 10);
        k = k / 10;
        n++;
    }
    if (n == 4 && set1.equals(set2))
        return true;
    return false;
}

public static void main(String agrs[]) {
    for (int i = 1023; i  k)
                    break;
                if (i % vInteger == 0 && isNum(i, k, vInteger))
                    System.out.println(vInteger + " * " + k + " = " + i);
                else
                    continue;
            }
            //每次循环清空集合
            set.clear();
        } else {
            set.clear();
            continue;
        }
    }
}

}

运行结果

6 * 201 = 1206
6 * 210 = 1260
21 * 60 = 1260
15 * 93 = 1395
35 * 41 = 1435
3 * 501 = 1503
3 * 510 = 1530
30 * 51 = 1530
21 * 87 = 1827
27 * 81 = 2187
9 * 351 = 3159
8 * 473 = 3784

答案

12种

蓝桥杯-扑克序列

蓝桥杯->扑克序列

1441185437

摘要:本题是2014年第五届蓝桥杯全国软件大赛预赛A组第6题,结果填空题。

题目描述

标题:扑克序列
A A 2 2 3 3 4 4, 一共4对扑克牌。请你把它们排成一行。
要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌。
请填写出所有符合要求的排列中,字典序最小的那个。
例如:22AA3344 比 A2A23344 字典序小。当然,它们都不是满足要求的答案。
请通过浏览器提交答案。“A”一定不要用小写字母a,也不要用“1”代替。字符间一定不要留空格。
解题思路

本题可以看成对字符串的处理,思路很清晰, 遍历字符串的全部排序,找到符合的字符串即可。
满足排序的有[2342A3A4, 4A3A2432],取第一个即可。
代码实现

package lanqiaobei;

import java.util.HashSet;

/**

  • @date 2015-9-2
  • @author Ape
  • /

public class PuKeList {

private static HashSet<String> set = new HashSet<String>();

public static void putStr(StringBuilder s1, StringBuilder s2) {
    if (s1.length() == 0 && find(s2.toString()))
        set.add(s2.toString());
    for (int i = 0; i < s1.length(); i++)
        put(new StringBuilder(s1).deleteCharAt(i),
                new StringBuilder(s2).append(s1.charAt(i)));
}

public static void main(String[] args) {
    String str = "AA223344";
    putStr(new StringBuilder(str), new StringBuilder());
    System.out.println(set);
}

public static boolean find(String str) {
    int a = str.indexOf("A");
    int a1 = str.lastIndexOf("A");
    int b = str.indexOf("2");
    int b1 = str.lastIndexOf("2");
    int c = str.indexOf("3");
    int c1 = str.lastIndexOf("3");
    int d = str.indexOf("4");
    int d1 = str.lastIndexOf("4");
    if (a1 - a == 2 && b1 - b == 3 && c1 - c == 4 && d1 - d == 5)
        return true;
    return false;
}

}

蓝桥杯-Huffuman树

1441649839

摘要:本题是蓝桥杯练习题。
题目描述

标题: Huffman树
Huffman树在编码中有着广泛的应用。在这里,我们只关心Huffman树的构造过程。
给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的过程如下:

  1. 找到{pi}中最小的两个数,设为pa和pb,将pa和pb从{pi}中删除掉,然后将它们的和加入到{pi}中。这个过程的费用记为pa + pb。
  2. 重复步骤1,直到{pi}中只剩下一个数。
    在上面的操作过程中,把所有的费用相加,就得到了构造Huffman树的总费用。
    本题任务:对于给定的一个数列,现在请你求出用该数列构造Huffman树的总费用。

例如,对于数列{pi}={5, 3, 8, 2, 9},Huffman树的构造过程如下:

  1. 找到{5, 3, 8, 2, 9}中最小的两个数,分别是2和3,从{pi}中删除它们并将和5加入,得到{5, 8, 9, 5},费用为5。
  2. 找到{5, 8, 9, 5}中最小的两个数,分别是5和5,从{pi}中删除它们并将和10加入,得到{8, 9, 10},费用为10。
  3. 找到{8, 9, 10}中最小的两个数,分别是8和9,从{pi}中删除它们并将和17加入,得到{10, 17},费用为17。
  4. 找到{10, 17}中最小的两个数,分别是10和17,从{pi}中删除它们并将和27加入,得到{27},费用为27。
  5. 现在,数列中只剩下一个数27,构造过程结束,总费用为5+10+17+27=59。
    输入格式
    输入的第一行包含一个正整数n(n<=100)。
    接下来是n个正整数,表示p0, p1, …, pn-1,每个数不超过1000。
    输出格式
    输出用这些数构造Huffman树的总费用。
    样例输入
    5
    5 3 8 2 9
    样例输出
    59
    解题思路

循环,对数组排序。
代码实现

package com.ape.lqb;

import java.util.Arrays;
import java.util.Scanner;

/**

  • @author Ape
  • @date 2015-9-8
  • /

public class Huffuman {

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    while (scanner.hasNext()) {
        int num = scanner.nextInt();
        int[] ape = new int[num];

        for (int i = 0; i < num; i++) 
            ape[i] = scanner.nextInt(); 
            int sum = 0; int k = 0; 
            while (num > 1) {
            Arrays.sort(ape);
            k = ape[0] + ape[1];
            sum = sum + k;
            ape[0] = k;
            ape[1] = Integer.MAX_VALUE;
            num--;
        }
        System.out.println(sum);
    }
}

}

蓝桥杯-FJ的字符串

1441886553

摘要:本题是蓝桥杯练习题。
题目描述

问题描述
FJ在沙盘上写了这样一些字符串:
A1 = “A”
A2 = “ABA”
A3 = “ABACABA”
A4 = “ABACABADABACABA”
… …
你能找出其中的规律并写所有的数列AN吗?
输入格式
仅有一个数:N ≤ 26。
输出格式
请输出相应的字符串AN,以一个换行符结束。输出中不得含有多余的空格或换行、回车符。
样例输入
3
样例输出
ABACABA
解题思路

思路清晰明了,一看就知道是用递归输出,不解释。
代码实现

package com.ape.lqb;

import java.util.Scanner;
/**

  • @author Ape

  • @date 2015-9-9

  • /
    public class FJString {

    public static void ape(char a, int n) {

    if (n == 1)
        System.out.print((char) a);
    else {
        ape((char) (a - 1), n - 1);
        System.out.print((char) a);
        ape((char) (a - 1), n - 1);
    }

    }

    public static void main(String[] args) {

    Scanner scanner = new Scanner(System.in);
    while (scanner.hasNext()) {
        int i = scanner.nextInt();
        ape((char) ('A' + i - 1), i);
        System.out.println();
    }

    }

}

PS

昨晚夜夜笙歌回来,早上迷迷糊糊醒来,毛概课无聊水了一题简单的题目,趁喝牛奶的时间,趁着没断网,来一发

蓝桥杯-高精度加法

1441896553

摘要:本题是蓝桥杯练习题。
题目描述

输入两个整数a和b,输出这两个整数的和。a和b都不超过100位。
算法描述
由于a和b都比较大,所以不能直接使用语言中的标准数据类型来存储。对于这种问题,一般使用数组来处理。
定义一个数组A,A[0]用于存储a的个位,A[1]用于存储a的十位,依此类推。同样可以用一个数组B来存储b。
计算c = a + b的时候,首先将A[0]与B[0]相加,如果有进位产生,则把进位(即和的十位数)存入r,把和的个位数存入C[0],即C[0]等于(A[0]+B[0])%10。然后计算A[1]与B[1]相加,这时还应将低位进上来的值r也加起来,即C[1]应该是A[1]、B[1]和r三个数的和.如果又有进位产生,则仍可将新的进位存入到r中,和的个位存到C[1]中。依此类推,即可求出C的所有位。
最后将C输出即可。
输入格式
输入包括两行,第一行为一个非负整数a,第二行为一个非负整数b。两个整数都不超过100位,两数的最高位都不是0。
输出格式
输出一行,表示a + b的值。
样例输入
20100122201001221234567890
2010012220100122
样例输出
20100122203011233454668012

解题思路

大一时候在ACM基础题用C语言解过此题,一样的算法,对字符的处理
代码实现

package com.ape.lqb;

import java.util.Scanner;

/**

  • @author Ape
  • @date 2015-9-10
  • /

public class Sum {

public static void main(String[] args) {
    String a, b;
    int ape, i, a1, b1;
    char[] c = new char[1001];
    Scanner scanner = new Scanner(System.in);
    while (scanner.hasNext()) {
        a = scanner.nextLine();
        b = scanner.nextLine();
        ape = 0;
        for (i = 0, a1 = a.length() - 1, b1 = b.length() - 1; a1 >= 0
                || b1 >= 0; a1--, b1--, i++) {
            if (a1 >= 0 && b1 >= 0)
                c[i] = (char) (a.charAt(a1) + b.charAt(b1) + ape - '0');
            else if (a1 >= 0 && b1 < 0) c[i] = (char) (a.charAt(a1) + ape); else if (a1 < 0 && b1 >= 0)
                c[i] = (char) (b.charAt(b1) + ape);
            ape = 0;
            if (c[i] > '9') {
                c[i] = (char) (c[i] - 10);
                ape = 1;
            }
        }
        if (ape == 1)
            System.out.print("1");
        while (--i >= 0)
            System.out.print(c[i]);
    }
}

}

运行示例

输入:6666666666666666666666666666666546464384385445153548743
输入:2345951947513794184352124627427635451323443504705437340507535370485735578143
输出:2345951947513794184358791294094302117990110171372103886971919755930889126886
PS

涂涂已来电,夜夜笙歌,走起。

DFS深度优先搜索

1457972626

不得不说的暴力的dfs深度搜索法,临时抱佛脚,过几天是蓝桥杯省赛,花一两天时间练习dfs

题目不求多练,主要是靠理解。

废话不说,列几道刚水过的题
题目描述

标题:李白打酒

话说大诗人李白,一生好饮。幸好他从不开车。

一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:

无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。

这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。

请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
解题思路

题目一览而过,最直接的就是dfs
代码实现

public class LiBaiHeJiu {

private static int count = 0;

static char[] s = new char[20];

static int f(int d, int h, int j) {
    if (d > 0)
        f(d - 1, h, j * 2);
    if (h > 0)
        f(d, h - 1, j - 1);
    if (d == 0 && h == 1 && j == 1)
        count++;
    return count;
}

static void m(int d, int h, int j) {
    if (d < 0 || h < 0 || j < 0)
        return;
    if (d == 0 && h == 1 && j == 1) {
        System.out.println(s.toString());
        count++;
    }
    s[d + h - 1] = 'a';
    f(d - 1, h, j * 2);
    s[d + h - 1] = 'b';
    f(d, h - 1, j - 1);
}

public static void main(String agrs[]) {
    m(5, 10, 2);
    System.out.println(count);
}

}

题目描述

题目标题: 第39级台阶
小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!
站在台阶前,他突然又想着一个问题:
如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?
请你利用计算机的优势,帮助小明寻找答案。

要求提交的是一个整数。
注意:不要提交解答过程,或其它的辅助说明文字。
题目思路

一看题目可以选择递归,可以使用dfs,下面是使用dfs解法
代码实现

/**

  • 39级阶梯问题

  • @author Ape

  • /
    public class JT {

    static int count = 0;

    static void w(int n, int step) {

    if (n < 0)
        return;
    if (n == 0 && step % 2 == 0) {
        count++;
        return;
    }
    w(n - 1, step + 1);
    w(n - 2, step + 1);

    }

    public static void main(String agrs[]) {

    w(39, 0);
    System.out.println(count);

    }
    }

第七届蓝桥杯省赛

第七届蓝桥杯省赛

1458487403

题目下载

不得不说,幸好练习了dfs,除了前面几道简单的填空题就不说了,后面从第六题开始一看题目说是要遍历的就用dfs搞,搞不出再说。

前面8道题目用不到1个小时就做出来并且验算完,差距就是最后两题。就像坐我隔离比赛的同学说会做的都做了,不会做的也做不出来。

写完跟我隔离比赛同学聊了1个多小时,好玩,说他今早5点就坐车来比赛,还跟我说困了要睡会待会叫我。

很侥幸的除了最后一题没算出其他的都搞掂了.
第六题

题目描述

凑算式

B DEF
A + — + ——- = 10
C GHI

(如果显示有问题,可以参见【图1.jpg】)

这个算式中AI代表09的数字,不同的字母代表不同的数字。

比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。

这个算式一共有多少种解法?

注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。

解题思路

当时我想都没想直接dfs,结果真算出来了哈哈

代码实现

public class A6 {

static int[] vis = new int[10];  //标记数组
static int[] m = new int[10];  //
static int count = 0;

static void dfs(int n) {
    if (n == 10) {  //此时1-9已赋值完毕,并验证条件
        int a = m[1];
        double b = (double) m[2] / m[3];
        double c = (double) (m[4] * 100 + m[5] * 10 + m[6])
                / (m[7] * 100 + m[8] * 10 + m[9]);
        if (a + b + c == 10.0) {
            count++;
            for (int i = 1; i <= 9; i++)
                System.out.print(m[i]);
            System.out.println();
            return;
        }
    }
    for (int i = 1; i <= 9; i++)
        if (vis[i] == 0) {  //判断标记已有的位
            vis[i] = 1;  //标记i已经使用
            m[n] = i;  //赋值
            dfs(n + 1);
            vis[i] = 0;  //取消标记
        }
}

public static void main(String[] args) {
    dfs(1);
    System.out.println(count);
}

}

运行结果

29
第七题

题目描述

搭积木

小明最近喜欢搭数字积木,
一共有10块积木,每个积木上有一个数字,0~9。

搭积木规则:
每个积木放到其它两个积木的上面,并且一定比下面的两个积木数字小。
最后搭成4层的金字塔形,必须用完所有的积木。

下面是两种合格的搭法:

0
1 2
3 4 5
6 7 8 9

0
3 1
7 5 2
9 8 6 4

请你计算这样的搭法一共有多少种?

请填表示总数目的数字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

解题思路

与第六题一致,只是验证条件改一下,明摆的送分题
第八题

题目描述

冰雹数

任意给定一个正整数N,
如果是偶数,执行: N / 2
如果是奇数,执行: N * 3 + 1

生成的新的数字再执行同样的动作,循环往复。

通过观察发现,这个数字会一会儿上升到很高,
一会儿又降落下来。
就这样起起落落的,但最终必会落到“1”
这有点像小冰雹粒子在冰雹云中翻滚增长的样子。

比如N=9
9,28,14,7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1
可以看到,N=9的时候,这个“小冰雹”最高冲到了52这个高度。

输入格式:
一个正整数N(N<1000000)
输出格式:
一个正整数,表示不大于N的数字,经过冰雹数变换过程中,最高冲到了多少。

解题思路

竟然这题比前面两题还简单,不想说话
第九题

题目描述

四平方和

四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多4个正整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。

比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符号表示乘方的意思)
对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对4个数排序:
0 <= a <= b <= c <= d
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法
程序输入为一个正整数N (N<5000000)
要求输出4个非负整数,按从小到大排序,中间用空格分开
例如,输入:
5
则程序应该输出:
0 0 1 2
再例如,输入:
12
则程序应该输出:
0 2 2 2
再例如,输入:
773535
则程序应该输出:
1 1 267 838
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 3000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
解题思路

思路不难,都是遍历,但是优化是一个难题,当时我没有想出来更好的优化方法,后边回去研究研究想起来以前做过的立方和优化的方法,哎呀,真行了。

代码实现

public class A9 {

static int[] mpt = new int[5000010];
static int n;

static void init() {
    for (int i = 0; i * i <= n; i++)
        for (int j = 0; j * j <= n; j++)
            if (i * i + j * j <= n)
                mpt[i * i + j * j] = 1;
}

public static void main(String[] args) {
    boolean flag = false;
    Scanner scanner = new Scanner(System.in);
    n = scanner.nextInt();
    init();
    for (int i = 0; i * i <= n; i++) {
        for (int j = 0; j * j <= n; j++) {
            if (mpt[n - i * i - j * j] == 0)
                continue;// 如果剩下的差用两个完全平方数不能组合出来就不继续
            for (int k = 0; k * k <= n; k++) {
                int temp = n - i * i - j * j - k * k;
                double w = Math.sqrt(temp);
                if (w == (int) w) {
                    System.out.printf("%d %d %d %d ", i, j, k, (int) w);
                    flag = true;
                    break;
                }
            }
            if (flag)
                break;
        }
        if (flag)
            break;
    }
    scanner.close();
}

}

第十题dfs搞不出来,难度相当。

BFS解决迷宫问题

1462463343

听说这个月是蓝桥杯的决赛,嗯,所以我又要临时抱佛脚了

这两天练习BFS广度优先搜索算法,看了一下算法思想,没错就是它http://rapheal.iteye.com/blog/1526861

按我来理解其实就跟DFS深度探索差不多,都是遍历,深度是无限的往下遍历,广度是寻找可通行的路径

嗯是的,BFS、很重要的一个算法,可以使用栈的先进后出或者队列的先进先出思想来解决。

然后我水了一题简单而典型的迷宫问题

题目出自:hncu ACM练习1102
题目描述

小明置身于一个迷宫,请你帮小明找出从起点到终点的最短路程。

小明只能向上下左右四个方向移动。
输入格式

输入包含多组测试数据。输入的第一行是一个整数T,表示有T组测试数据。

每组输入的第一行是两个整数N和M(1<=N,M<=100)。

接下来N行,每行输入M个字符,每个字符表示迷宫中的一个小方格。

字符的含义如下:

‘S’:起点

‘E’:终点

‘-’:空地,可以通过

‘#’:障碍,无法通过

输入数据保证有且仅有一个起点和终点。
输出

对于每组输入,输出从起点到终点的最短路程,如果不存在从起点到终点的路,则输出-1。
JAVA代码实现

public class SimpleBFS {

class Node {
    int x, y, step;

    Node() {
    }

    Node(int x, int y, int step) {
        this.x = x;
        this.y = y;
        this.step = step;
    }
}

static char map[][] = new char[105][105];
static int vis[][] = new int[105][105]; // 标记探索过的位置
static int dir[][] = new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } }; // 探索规则
static int n, m, sx, sy, ans;

// 检查是否越界符合规则
static boolean judge(int x, int y) {
    if (x < 0 || x >= n || y < 0 || y >= m)
        return true;
    if (vis[x][y] == 1 || map[x][y] == '#')
        return true;
    return false;
}

static void bfs() {
    int i;
    Queue<Node> Q = new LinkedList<Node>();
    SimpleBFS bfs = new SimpleBFS();
    Node a = bfs.new Node();
    Node next = bfs.new Node();
    Node top = bfs.new Node();
    a.x = sx;
    a.y = sy;
    a.step = 0;
    vis[a.x][a.y] = 1;
    Q.offer(a);
    while (!Q.isEmpty()) {
        top = Q.poll(); // 出列
        if (map[top.x][top.y] == 'E') {
            ans = top.step;
            return;
        }
        for (i = 0; i < 4; i++) {
            next = top;
            next.x += dir[i][0];
            next.y += dir[i][1];
            if (judge(next.x, next.y))
                continue;
            next.step = top.step + 1;
            vis[next.x][next.y] = 1; // 标记已探索的位置
            Q.offer(bfs.new Node(next.x, next.y, next.step)); // 入列
        }
    }
    ans = -1;
}

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

    n = scanner.nextInt();
    m = scanner.nextInt();
    int i, j;
    for (i = 0; i < n; i++)
        for (j = 0; j < m; j++)
            map[i][j] = scanner.next().charAt(0);
    // 找到开始位置
    for (i = 0; i < n; i++)
        for (j = 0; j < m; j++) {
            if (map[i][j] == 'S') {
                sx = i;
                sy = j;
            }
        }
    bfs();
    System.out.println("最短路径:" + ans);

    scanner.close();
}

}

运行结果

通过

解题反馈

嗯,不得不说,解题时候遇到一个很无解的问题,算法是没问题的,我还特意用C语言写了一遍,对,算法确实没问题,结果是可以出来的,但是没问题就是最大的问题。

一次又一次的测试,起码10次,当然过程会很烦躁,跑完步回来的我灵机一动,天大的问题出现了。

问题在入列这一行,当时我是这样写的

Q.offer(next); // 入列

我天,经过我测试,真是我错了,Queue测试

测试代码

public class QueueTest {

class Node {
    int x, y, step;

    Node(int x, int y) {
        this.x = x;
        this.y = y;
    }

    Node() {
    }
}

public static void main(String[] args) {
    // TODO Auto-generated method stub

    Queue<Node> queueQ = new LinkedList<Node>();
    QueueTest queueTest = new QueueTest();
    queueQ.offer(queueTest.new Node(1, 1));
    queueQ.offer(queueTest.new Node(2, 2));
    queueQ.offer(queueTest.new Node(3, 3));
    queueQ.offer(queueTest.new Node(4, 4));
    System.out.println("--当前队列--");
    for (Node q : queueQ) {
        System.out.println("x:" + q.x + "--y:" + q.y);
    }
    Node a = queueQ.poll();
    System.out.println("poll=>" + "x:" + a.x + "--y:" + a.y); // 返回第一个元素,并在队列中删除
    System.out.println("--删除顶部后的队列--");
    for (Node q : queueQ) {
        System.out.println("x:" + q.x + "--y:" + q.y);
    }
    System.out.println("--添加一个元素后的当前队列--");
    queueQ.offer(queueTest.new Node(99, 99));
    for (Node q : queueQ) {
        System.out.println("x:" + q.x + "--y:" + q.y);
    }
    System.out.println("--添加一个元素后的队列--");
    Node Ape = queueTest.new Node();
    Ape.x = 88;
    Ape.y = 88;
    queueQ.offer(Ape);
    for (Node q : queueQ) {
        System.out.println("x:" + q.x + "--y:" + q.y);
    }
    System.out.println("--添加一个原有对象的元素后的队列--");
    Ape.x = 881;
    Ape.y = 881;
    queueQ.offer(Ape);
    for (Node q : queueQ) {
        System.out.println("x:" + q.x + "--y:" + q.y);
    }

}

}

运行结果

–当前队列–
x:1–y:1
x:2–y:2
x:3–y:3
x:4–y:4
poll=>x:1–y:1
–删除顶部后的队列–
x:2–y:2
x:3–y:3
x:4–y:4
–添加一个元素后的当前队列–
x:2–y:2
x:3–y:3
x:4–y:4
x:99–y:99
–添加一个元素后的队列–
x:2–y:2
x:3–y:3
x:4–y:4
x:99–y:99
x:88–y:88
–添加一个原有对象的元素后的队列–
x:2–y:2
x:3–y:3
x:4–y:4
x:99–y:99
x:881–y:881
x:881–y:881

我能说什么

兰顿蚂蚁

1462541987

摘要:本题是2014年第五届蓝桥杯全国软件大赛预赛C组第9题,编程题。
题目描述

标题:兰顿蚂蚁

兰顿蚂蚁,是于1986年,由克里斯·兰顿提出来的,属于细胞自动机的一种。

平面上的正方形格子被填上黑色或白色。在其中一格正方形内有一只“蚂蚁”。

蚂蚁的头部朝向为:上下左右其中一方。

蚂蚁的移动规则十分简单:

若蚂蚁在黑格,右转90度,将该格改为白格,并向前移一格;

若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。

规则虽然简单,蚂蚁的行为却十分复杂。刚刚开始时留下的路线都会有接近对称,像是会重复,但不论起始状态如何,蚂蚁经过漫长的混乱活动后,会开辟出一条规则的“高速公路”。

蚂蚁的路线是很难事先预测的。

你的任务是根据初始状态,用计算机模拟兰顿蚂蚁在第n步行走后所处的位置。
数据格式

输入数据的第一行是 m n 两个整数(3 < m, n < 100),表示正方形格子的行数和列数。

接下来是 m 行数据。

每行数据为 n 个被空格分开的数字。0 表示白格,1 表示黑格。

接下来是一行数据:x y s k, 其中x y为整数,表示蚂蚁所在行号和列号(行号从上到下增长,列号从左到右增长,都是从0开始编号)。s 是一个大写字母,表示蚂蚁头的朝向,我们约定:上下左右分别用:UDLR表示。k 表示蚂蚁走的步数。

输出数据为两个空格分开的整数 p q, 分别表示蚂蚁在k步后,所处格子的行号和列号。

输入

5 6
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
2 3 L 5

输出

1 3

资源约定

峰值内存消耗(含虚拟机) < 256M

CPU消耗 < 1000ms
解题思路

看看题目以为是迷宫问题,想练习练习BFS,谁知道不是,我直接用DFS搞了他
代码实现

public class MyDFS {

static int[][] map = new int[101][101];
static int n, m, sx, sy, step;
static char dirChar;

static void dfs(int n, char dir) {
    if (n == step) {
        System.out.println(sx + "  " + sy);
        return;
    }
    if (map[sx][sy] == 0) { // 白格
        map[sx][sy] = 1;
        // dir为当前的方向, dirChar为按规则转向后的方向
        switch (dir) {
        case 'U':
            dirChar = 'L';
            sy -= 1;
            break;
        case 'D':
            dirChar = 'R';
            sy += 1;
            break;
        case 'R':
            dirChar = 'U';
            sx -= 1;
            break;
        case 'L':
            dirChar = 'D';
            sx += 1;
            break;
        }
    } else { // 黑格
        map[sx][sy] = 0;
        switch (dir) {
        case 'U':
            dirChar = 'R';
            sy += 1;
            break;
        case 'D':
            dirChar = 'L';
            sy -= 1;
            break;
        case 'R':
            dirChar = 'D';
            sx += 1;
            break;
        case 'L':
            dirChar = 'U';
            sx -= 1;
            break;
        }
    }
    dfs(n + 1, dirChar);
}

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    n = scanner.nextInt();
    m = scanner.nextInt();
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            map[i][j] = scanner.nextInt();
    sx = scanner.nextInt();
    sy = scanner.nextInt();
    String t = scanner.next();
    dirChar = t.charAt(0);
    step = scanner.nextInt();
    dfs(0, dirChar);
    scanner.close();
}

}

地宫取宝

1462629600

昨晚睡觉前本来想刷一题,结果遇上了难度相当的题,不,不能这么说,应该说是我老毛病又犯了,看错题!

把k看成是所有宝贝加起来的价值,然后我马上想到用DFS+DP,呵呵~

然后今天在去南站的车上,重新看了遍题目,my god,不想说话。

说到南站,是因为老师帮买票说我身份冒用,弄不了,白跑一趟。

回来马上用dfs记忆化搜索搞掂了

跑完十几圈回来马上贴题,部门的已经在外面吃宵夜等了我一个多小时了,马上洗澡,等我
题目描述

标题:地宫取宝

X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。
数据格式

输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)
接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值
要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。

例如,输入

2 2 2
1 2
2 1

输出

2

输入

2 3 2
1 2 3
2 1 5

输出

14

峰值内存消耗(含虚拟机) < 256M

CPU消耗 < 2000ms
代码实现

public class DFS_5c9 {
static int n, m, k, ans = 0, mod = 1000000007;
static int[][] map = new int[51][51];

/**
 * 
 * @param num
 *            记录宝贝总数
 * @param maxValue
 *            记录当前宝贝最大值
 * @param x
 * @param y
 * 
 */
static void dfs(int num, int maxValue, int x, int y) {
    if (x >= n || y >= m || num > k)
        return;
    if (x == n - 1 && y == m - 1) {
        // 到达出口时的宝贝map[x][y] 大于 手上最大的宝贝
        if (map[x][y] > maxValue) {
            if (num == k || num == k - 1) // 当手上总数为k-1必拿+1,当手上总数为k不拿+1
                ans++;
        } else if (num == k) { // 当手上总数为k
            ans++;
        }
        return;
    }
    // x,y对应的宝贝map[x][y] 大于 手上最大的宝贝
    if (map[x][y] > maxValue) {
        dfs(num + 1, map[x][y], x, y + 1);
        dfs(num + 1, map[x][y], x + 1, y);
    }
    dfs(num, maxValue, x + 1, y);
    dfs(num, maxValue, x, y + 1);
}

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    n = scanner.nextInt();
    m = scanner.nextInt();
    k = scanner.nextInt();
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            map[i][j] = scanner.nextInt();
    dfs(0, 0, 0, 0);
    System.out.println(ans % mod);
    scanner.close();
}

}