ZOJ 3861 安卓图案锁屏 DFS深搜

本文探讨了如何解决给定九宫格数字的组合密码问题,通过DFS深度优先搜索算法来计算所有可能的密码组合方案数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3861

想不大ZOJ访问速度这么慢。

题意:给定九宫格中的一些数字,求这些数字能组成的密码方案种数。主要判断能否继续往下搜索

 

代码:

#include<iostream>
#include<sstream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<string>
#define LL long long
#define INF 0x7fffffff

using namespace std;
int a[20],n,vis[20],vis2[20];
int cnt,tot,ans[20];//分别记录方案数,和有效点数及答案数组

int isok(int x,int y){//判断从x到y是否合法,即中间点是否访问过
    if(x+y==10 && !vis2[5]) return 0;
    if(min(x,y)==1 && max(x,y)==3 && !vis2[2]) return 0;
    if(min(x,y)==7 && max(x,y)==9 && !vis2[8]) return 0;
    if(min(x,y)==1 && max(x,y)==7 && !vis2[4]) return 0;
    if(min(x,y)==3 && max(x,y)==9 && !vis2[6]) return 0;
    return 1;
}

void dfs(int t,int count,int op){//目前所在下标,已经ans存储的个数,输出标志
    if(count==tot){
        if(op){
            for(int i=1;i<tot;i++)
                printf("%d ",ans[i]);
            printf("%d\n",ans[tot]);
            return;
        }
        cnt++;return;
    }
    for(int i=0;i<tot;i++)
        if(!vis[i] && isok(a[t],a[i])){
            vis[i]=1;vis2[a[i]]=1;
            ans[count+1]=a[i];
            dfs(i,count+1,op);
            vis[i]=0;vis2[a[i]]=0;
        }
}

int main(){
    //freopen("D:\\in.txt","r",stdin);
    int T;cin>>T;
    while(T--){
        cin>>n;
        tot=0;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++){
            int t;cin>>t;
            if(!vis[t]) vis[t]=1,a[tot++]=t;//感觉可能存在重复输入
        }

        sort(a,a+tot);
        cnt=0;
        memset(vis,0,sizeof(vis));//ans数组访问标志
        memset(vis2,0,sizeof(vis2));//九宫格访问标志
        for(int j=0;j<2;j++){//这里进行了两次DFS,一次求cnt,一次输出,是为了节约空间
            if(j) cout<<cnt<<endl;
            for(int i=0;i<tot;i++){
                vis[i]=1;vis2[a[i]]=1;
                ans[1]=a[i];
                dfs(i,1,j);
                vis[i]=0;vis2[a[i]]=0;
            }
        }
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值