第七届蓝桥杯省赛--方格填数--DFS或全排列

 

第七届其他题目解析链接

 

答案是 1580

 

思路

两个做法  DFS或者全排列  (全排列要好写些)

 

DFS

一共10个位置  10个数

第一个位置 可以放0-9   接下来的位置要满足相邻位置不连续   所以我们dfs搜索所有可能的方案并计数

 

我们先建立坐标  如图所示

然后 我们DFS的方向需要注意一下  

这个题的解法巧妙就在于我们 DFS的顺序

我们按照从左到右的方向去DFS

走到最右边的时候  我们不往下走   而是另起一行 继续从左往右   如图

为什么这么做呢 ?

这样做可以大大降低DFS的复杂度   好处如下(可以结合代码去看比较好理解

1、我们DFS的时候 可以有四个探测方向  但是按照这样做就只有向右探测一个方向了  到头了就另起一行

 

2、依据题意  我们在给一个位置放数字的时候 需要判断他的八个方向  看看相邻数字是否连续  但是我们用这种顺序去DFS就只用判断四个方向  左  左上  上  右上  因为按照这个顺序去填数  所填位置的下边和右边还没到呢  所以不用考虑下(左下  右下  正下)和右 

 

3、注意开头和结尾  (0,0)和(2,3)这两个位置是不能填数的   那么你判断边界的时候怎么判断呢  如果你以0<=x<=2 和0<=y<=3来判断呢是无法判断到(0,0)和(2,3)的  需要特判 ,而我们用这种dfs顺序呢,我们不需要特判。开头我们直接从(0,1)开始,避过了(0,0)。而结尾(2,3)刚好说明我们填数结束了,此时计数顺便结束递归就好了

ps:两个小细节

1、往左走是 (x,y-1)  左上走是(x-1,y-1)  正上是(x-1,y)  所以我们用一个转向数组,

int dir[4][2]={{0,-1},{-1,-1},{-1,0},{-1,1}};//x y分别加上  就代表左 左上  上 右上

2、要求数字不连续  我们直接判断差的绝对值大于一就好了

代码 及注释

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
int a[4][4];
int vis[11];
int cnt=0;
bool check(int x,int y,int v){
    //转向
    int dir[4][2]={{0,-1},{-1,-1},{-1,0},{-1,1}};//左 左上  上 右上
    for(int i=0;i<4;i++){
        int xx=x+dir[i][0];
        int yy=y+dir[i][1];
        if(xx<3 && xx>=0 && yy<4 && yy>=0){
            if(abs(a[xx][yy]-v)==1)return false;
        }
    }
    return true;
}
void DFS(int x,int y){
    if(x==2&&y==3){cnt++;return;}//遇到(2,3)说明结束
    
    for(int i=0;i<=9;i++){
        //要确保这个数没被选过并且放在这里符合题意
        if(vis[i]==0&&check(x,y,i)){
        
            vis[i]=1;a[x][y]=i;
    
            if(y+1<4) DFS(x,y+1);//向右搜索
            else DFS(x+1,0);//另起一行
            
            vis[i]=0;
        }
    }
    return ;
}
int main(){
    for(int i=0;i<4;i++)//初始化一个较小的数
        for(int j=0;j<4;j++)
            a[i][j]=-20;
            
    DFS(0,1);//从(0,1)开始
    printf("%d\n",cnt);
    return 0;
}

 

全排列做法

这个做法比DFS要好写些

一共只有10个空位  位置是固定的  数字呢就是0-9   我们把0-9做个全排列  那么所有的填数方案就出来了

筛选出符合要求的  记下来就好了

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
int a[11]={0,1,2,3,4,5,6,7,8,9};
bool c(int x,int y){
    if(abs(x-y)==1)return false;
    else return true;
}
int main(){
    int cnt=0;
    do{
        if(c(a[1],a[0]))
        if(c(a[2],a[1]))
        if(c(a[3],a[0]))
        if(c(a[4],a[3])&&c(a[4],a[0])&&c(a[4],a[1]))
        if(c(a[5],a[4])&&c(a[5],a[0])&&c(a[5],a[1])&&c(a[5],a[2]))
        if(c(a[6],a[5])&&c(a[6],a[1])&&c(a[6],a[2]))
        if(c(a[7],a[3])&&c(a[7],a[4]))
        if(c(a[8],a[7])&&c(a[8],a[3])&&c(a[8],a[4])&&c(a[8],a[5]))
        if(c(a[9],a[8])&&c(a[9],a[4])&&c(a[9],a[5])&&c(a[9],a[6]))
        cnt++;
    }while(next_permutation(a,a+10));
    printf("%d\n",cnt);
    return 0;
}

 

 

全部评论

相关推荐

01-30 09:45
燕山大学 Java
喵_coding:这种直接跑就完事了 哪有毕业了才签合同 任何offer和三方都没有的
点赞 评论 收藏
分享
03-13 00:04
已编辑
吉林大学 Java
约面的挺突然。。狠下心接了1.自我介绍2.讲讲JAVA的反射3.可以继续讲讲AOP,动态代理[&nbsp;因为讲反射不小心吟唱到了例如AOP的动态代理,但是这块记忆的非常不熟,结果磕磕绊绊&nbsp;]4.项目我看你写了AOP和注解,具体怎么实现滑动窗口限流的[&nbsp;梦到什么说什么,吟唱八股发散千万不要散到自己不熟悉的区域&nbsp;]5.也讲讲为什么另一个项目选择令牌桶,具体流程6.&nbsp;OK,讲讲&nbsp;Redis&nbsp;的数据类型?还有吗?就了解这五种嘛[&nbsp;把5个的基础类型从应用对比到历届底层全都吟唱了一遍。一句还有吗直接没力气了,简历就写了理解5种,别的我是真一点没看TT&nbsp;]7.讲讲Redission分布式锁实现8.这个指数退避怎么实现的9.在这里有考虑去保障幂等性嘛10.这里为什么使用指数退避呢?&nbsp;什么时候用均匀重传[已经晕过去了说不了解,刚说了后就意识到,估计应该说指数退避能缓解压力防止下游服务器雪崩之类的]11.ok,那讲讲JMM12.讲讲RocketMQ如何保证的不丢消息13.讲讲RocketMQ延迟消息原理14.讲讲项目Redis实现会话记忆这一块15.如果ai调用function&nbsp;calling出现幻觉,有考虑怎么解决吗?[&nbsp;不了解,面试官说什么接口幂等化,高危操作人工防护,没在听,感觉人已经飞升了TT&nbsp;]16.mcp了解嘛?和function&nbsp;calling有什么区别[&nbsp;依旧不了解,只能说了个前者规范架构抽象解耦,后者耦合高只能算个工具调用]17.AI生成代码的代码质量怎么保障,那平时如何review的呢18.算法。lc215&nbsp;&nbsp;数组中最大第k个元素19.打算考研还是本科就业20.反问1️⃣有哪里不足,有哪些需要提高的部分。[主要说知识广度不够,多刷算法,让我别太紧张]2️⃣部门业务会做什么人生第二次面试。感觉大厂面试官的气场压力很大应该凉了不过这次面试非常锻炼心态,多面试,多面试。
冰炸橙汁_不做oj版:redis除了五种基本数据类型,其他的几种还是要掌握一下的,挺常用
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务