蓝桥杯-方格填数

方格填数

如下的10个格子
+–+–+–+
| | | |
+–+–+–+–+
| | | | |
+–+–+–+–+
| | | |
+–+–+–+

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

填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)

一共有多少种可能的填数方案?

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

一开始直接用dfs八个方向进行搜索,结果很大,也不知道问题在哪里
最后直接一个方格一个方格的填,就出现了答案
先说一下思路吧, 对于每一个0-9的数进行标记,对于每一个坐标点进行填数
对填写的数进行判断如果可以直接填写,然后进行下一个dfs
如果不可以进行寻找合适的数字,找不到直接回溯到上一个dfs

答案:1580
java代码实现:
朋友做的代码效率比我高出N倍…:

    package com.tjrac_java_2;

public class QuanPaiLie {
    static int all=0;
    static int[] num=
    {
    -2,-2,-2,-2,-2,-2,
    -2,-2,10,10,10,-2,
    -2,10,10,10,10,-2,
    -2,10,10,10,-2,-2,
    -2,-2,-2,-2,-2,-2,
    };
    static int []useful={8,9,10,13,14,15,16,19,20,21};
    static int check(int i)//该位置方格的上,左,左上,右上
    {   
        if(num[i]==num[i-1]-1||num[i]==num[i-1]+1)
            return 0;
        else if(num[i]==num[i-6]-1||num[i]==num[i-6]+1)
            return 0;
        else if(num[i]==num[i-7]-1||num[i]==num[i-7]+1)
            return 0;
        else if(num[i]==num[i-5]-1||num[i]==num[i-5]+1)
            return 0;
        else
            return 1;
    }
    static int check_same(int i)//判断该方格中的数字是否被用过
    {
        for(int j=0;j<i;++j)
            if(num[useful[j]]==num[useful[i]])
                return 0;
        return 1;
    }
    static void func(int round)
    {
        if(round>9)//如果round>9表示已经给所有方格添加数字
        {   
            ++all;
            return ;
        }
        else
            for(int i=0;i<=9;++i)
                {
                    num[useful[round]]=i;//数字添加到方格中
                    if(check_same(round)==1&&check(useful[round])==1)//判断该方格数字是否已经用过,以及该填充的方格数字满足相邻不为1
                        func(round+1);//递归遍历下一个方格
                }
    }
    public static void main(String[] args) {
        func(0);
        System.out.println(all);
    }
}

自己代码(58000ms,呵呵。。。):

package com.tjrac_java_2;

public class SumCount {
    //考虑到边界问题把数组行列扩大两位
    static int count=0, sum = 0;//count表示已经填充数的字格数。sum表示最后输出结果
    static int[][] go = {{0,1},{1,0},{0,-1},{1,-1},{-1,0},{-1,1},{-1,-1},{1,1}};//右、下、左、左下、上、右上、左上、右下
    static int[][] newGo={{-1,0},{1,0},{0,-1},{0,1}};
    static int[] num = new int[10];//用来判断该数字是否用过,用过为1 否则为0
    static int[] road = new int[11];
    static int flag=0;
    static long start , end;
    public static void main(String[] args) {
        start = System.currentTimeMillis();
        int [][] a = new int [5][6];
        for (int i = 0; i < 10; i++) {
            num[i]=0;
        }
        for(int i=0;i<5;i++){
            for(int j=0;j<6;j++){
                a[i][j]=11;//表示可以访问,之所以为11因为方便判断不相邻
            }
        }
        for(int i=0;i<10;i++){
            a[1][2]=i;//控制第一个方格的值
            num[i]=1;//标记i不能再用了
            count++;
            flag=i;
            //road[i]=12;//路径
            DFS(a,1,2);
            a[1][2]=11;
            num[i]=0;
            count--;
        }
        System.out.println("总次数:"+sum);
        System.out.println("用时:"+(System.currentTimeMillis()-start));
//      for (int is : road) {
//          System.out.println(is);
//      }
    }

    private static void DFS(int[][] a, int x, int y) {
        //递归出口
        //表示10个数字填充完毕
        System.out.println("ok");
        if(count == 10 ){
            sum++;
            return ;
        }else{
            //for(int i = 0; i < 8; i ++){
                for(int i = 0; i < 4; i++){
                    //往相邻方格填数字
                    int xx = x + go[i][0];
                    int yy = y + go[i][1];
                    //判断边界,是否已经填充了数字,满足相邻不为1
                    if((xx==1&&yy==1) || (xx==3&&yy==4))continue;//因为11和44不能访问
                    if(xx >= 1 && xx <= 3 && yy >= 1 && yy <= 4 && a[xx][yy] ==11 ){
                        //往该方格中放数字
                        System.out.println("上个方格:"+"x:"+x+"->>y:"+y);
                        System.out.println("现在方格:"+"xx: "+xx+"  yy: "+yy);
                        for( int k = 0; k < 10; k++){
                            //判断该数字是否被用过,并且数字不相邻
                            if(num[k] == 0 && Math.abs(k-a[xx][yy+1])!=1 && Math.abs(k-a[xx+1][yy])!=1 && Math.abs(k-a[xx][yy-1])!=1 && Math.abs(k-a[xx+1][yy-1])!=1 &&Math.abs(k-a[xx-1][yy])!=1&& Math.abs(k-a[xx-1][yy+1])!=1 &&Math.abs(k-a[xx-1][yy-1])!=1&& Math.abs(k-a[xx+1][yy+1])!=1){
                                a[xx][yy] = k;System.out.println("填入数字:"+"xx: "+xx+"   "+yy+"   数字:"+k+"右边:"+a[xx][yy-1]);
                                num[k]=1;
                                count++;
                                //road[count]=xx*10+yy;
                                DFS(a,xx,yy);
                                a[xx][yy] = 11;
                                num[k]=0;
                                count--;System.out.println("填入的方格总数:"+count);
                /*              if(count<0){
                                    return;
                                }*/

                            }
                        }
                    }
                }
            //}
        }


    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值