深搜题

洛谷P1219 - 八皇后

我的思路是,按行顺序来放到列上,所以行不会重复,同时放到列上时,判断该列有没有占用,所以列不会重复,那么这个题,关键点就是处理对角线,可以发现,选择了一个点(x,y),那么他的两条对角线上的点都不能选了,发现这两条对角线上的点(x1,y1)分别满足x1+y1=x+y 和 x1-y1=x-y

那么在判断交叉线是用两个数组,一个记录x+y值占用过没,另一个记录x-y+n占用过没(因为可能有负数)

ps:本来我是用map来记录x+y值和x-y值的,不行!因为会有二者恰好相同,并且会超时(QwQ)

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const int N=20,mod=1e9+7;
const int INF=0x3f3f3f3f;

int ans[N];//ans[i]:=第i行放置到了第ans[i]列
int vis[N];
int n,cnt=0;
int cha[N*2],he[N*2];

void dfs(int line){//第line行在第x列
    if(line==n+1){
        cnt++;
        if(cnt<=3){
            for(int i=1;i<n;i++){
                printf("%d ",ans[i]);
            }
            printf("%d\n",ans[n]);
        }
        return ;
    }
    if(line>n+1){
        return ;
    }
    for(int i=1;i<=n;i++){//第i列
        int x=line+i,y=i-line+n;
        if(!vis[i]&&!he[x]&&!cha[y]){
            //printf("%d %d\n",line,i);
            he[x]=1;
            cha[y]=1;
            vis[i]=1;
            ans[line]=i;
            dfs(line+1);
            vis[i]=0;
            he[x]=0;
            cha[y]=0;
        }
    }
}

int main(){
    scanf("%d",&n);
    dfs(1);
    printf("%d\n",cnt);
}

洛谷P1101 - 单词方阵

我傻了,直接上了dfs,然后错错错,其实这个题明显要判断方向啊,朝着一个方向搜索下去!

而且本来是想暴力写的,但是dfs更简洁,把每一步存下来,搜到结果的时候再处理!

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const int N=105,mod=1e9+7;
const int INF=0x3f3f3f3f;
char t[8]={'y','i','z','h','o','n','g'};
char a[N][N];
int n,vis[N][N];
struct A{
    int x,y;
}path[10];
int dx[8]={-1,-1,-1,0,1,1,1,0},dy[8]={-1,0,1,1,1,0,-1,-1};

void dfs(int x,int y,int dep,int fa){
    if(dep==7){
        for(int i=0;i<7;i++){
            vis[path[i].x][path[i].y]=1;
        }
        return ;
    }
    if(dep>7)return ;
    int nx=x+dx[fa],ny=y+dy[fa];
    if(nx>=0&&nx<n&&ny>=0&&ny<n&&a[nx][ny]==t[dep]){
        path[dep].x=nx;
        path[dep].y=ny;
        dfs(nx,ny,dep+1,fa);
    }
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%s",a[i]);
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(a[i][j]=='y'){
                path[0].x=i;path[0].y=j;
                for(int k=0;k<8;k++){
                    int nx=i+dx[k],ny=j+dy[k];
                    if(nx>=0&&nx<n&&ny>=0&&ny<n&&a[nx][ny]=='i'){
                        path[1].x=nx;path[1].y=ny;
                        dfs(nx,ny,2,k);
                    }
                }
            }
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(vis[i][j])printf("%c",a[i][j]);
            else printf("*");
        }
        printf("\n");
    }
}

洛谷P1162 - 填涂颜色

参考题解区第一的大佬思路

这个思路很巧妙,就是从不在圈内的0开始搜索,遇到1就停止了,那么1和1内部都搜不到,标记为2

但是我们怎么找不在圈内的0呢?

图存到a[1-n][1-n]里,我们把n*n的图向外扩一圈,从(0,0)开始搜就行了,总能找到“突破口”,除非图是被1全包围的

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const int N=35,mod=1e9+7;
const int INF=0x3f3f3f3f;
int n;
int a[N][N],vis[N][N];
typedef pair<int,int>P;
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};

void dfs(int x,int y){
    vis[x][y]=1;
    for(int i=0;i<4;i++){
        int nx=x+dx[i],ny=y+dy[i];
        if(nx>=0&&nx<=n+1&&ny>=0&&ny<=n+1&&!vis[nx][ny]&&a[nx][ny]!=1){
            dfs(nx,ny);
        }
    }
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&a[i][j]);
        }
    }
    dfs(0,0);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(vis[i][j])printf("0");
            else if(a[i][j]==1)printf("1");
            else printf("2");
            printf("%c",j==n?'\n':' ');
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值