ZOJ3861 Valid Pattern Lock

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=150302

题意:给定一个九宫格,给定一些能走的数字,走法按照手机图案的解锁方法来解锁,起点不定,求合法路线的总数并按照字典序输出他们

思路:暴力破解+DFS。刚开始的想法是把路线看成二维,一条一条判断是否合法,这种方法最大的问题就是会超时,而且例如1->3>1>4的路线不好表示,要假定一个点只能经过两次,搜索的深度瞬间增加了n个指数级。实际上由于点数小,可以把路线看成一维,只是有些路线在某些情况下不合法,穷举即可。莫名其妙的做了很久。

错误源码:

#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#include <map>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <functional>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cassert>
#include <bitset>
#include <stack>
#include <ctime>
#include <list>
#define INF 0x7fffffff
#define max3(a,b,c) (max(a,b)>c?max(a,b):c)
#define min3(a,b,c) (min(a,b)<c?min(a,b):c)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int const MAXN = 10;
int use[MAXN],uu[MAXN];
int org[MAXN];
int vis[4][4];
int re[MAXN];
int rec[362880+1];
int n;
int dy[12] = {-2,-1,0,1,2,-1,1,-2,-1,0,1,2};
int dx[12] = {-1,-1,-1,-1,-1,0,0,1,1,1,1,1};
int dir[MAXN] = {1,1,1e1,1e2,1e3,1e4,1e5,1e6,1e7,1e8};
int num,total;///num for all rec,total for not repeaty ones.
bool valid(int a)
{
    if(a<1 || a>3)
        return false;
    return true;
}
bool cmp(int a,int b)
{
    return a<b;
}
bool equ(int a[],int b[])
{
    int i;
    for(i=0; i<n; i++)
        if(a[i]!=b[i])
            return false;
    return true;
}
int X(int i)
{
    return i%3?i/3+1:i/3;
}
int Y(int i)
{
    return i%3?i%3:3;
}
void init()
{
    num = total = 0;
    memset(rec,0,sizeof(rec));
    memset(use,0,sizeof(use));
    int i,temp;
    for(i=0; i<n; i++){
        scanf("%d", &temp);
        use[temp] = 1;
        org[i] = temp;
    }
    sort(org,org+n);
}
void dfs(int now,int mark)
{
    int i;
    if(mark==n){
//        if(num>0 && equ(rec[num],re))
//            return;
        num++;
        for(i=0; i<n; i++){
            rec[num]= rec[num]*10 + re[i];
        }
//        printf("\nnum = %d\n",num);
//        for(i=0; i<n; i++)
//            printf("%d ",re[i]);
//        printf("\n\n");
    }
//    printf("now = %d mark = %d\n",now,mark);
    for(i=0; i<12; i++){
//        printf("now = %d\n",now);
        int tx = X(now)+dx[i];
        int ty = Y(now)+dy[i];
        int t = (tx-1)*3 + ty;
//        printf("first tx = %d ty = %d t = %d\n",tx,ty,t);
        if(valid(tx)&&valid(ty) && use[t] && vis[tx][ty]<2){
//            printf("second tx = %d ty = %d t = %d\n",tx,ty,t);
//            for(i=0; i<mark; i++)
//                printf("%d ",re[i]);
//            printf("\n");
            vis[tx][ty]++;
            if(uu[t]==0){
                uu[t] = 1;
                re[mark] = t;
                dfs(t,mark+1);
                uu[t] = 0;
            }
            else
                dfs(t,mark);
            vis[tx][ty]--;
        }
    }
}
void solve()
{
    int i,j;
    memset(vis,0,sizeof(vis));
    memset(uu,0,sizeof(uu));
    for(i=0; i<n ;i++){
        int t = org[i];
        int tx = X(t);
        int ty = Y(t);
        vis[tx][ty] = 1;
        re[0] = t;
        uu[t] = 1;
//        printf("org = %d\n",org[i]);
        dfs(t,1);
        vis[tx][ty] = 0;
        uu[t] = 0;
    }
    sort(rec,rec+num,cmp);
    for(i=1; i<=num; i++)
        if(rec[i]!=rec[i-1])
            total++;
    printf("%d\n",total);
    for(i=1; i<=num; i++){
        if(i==0 ||(i>0 && rec[i-1]!=rec[i])){
            int f = 1;
            int tt = rec[i];
            for(j=0; j<n; j++){
                if(f) f=0;
                else printf(" ");
                printf("%d",tt/dir[n-j]);
                tt = tt%dir[n-j];
//                printf("\nrec = %d\n",rec[i]);
            }
//            printf("%d",rec[i]);
            printf("\n");
        }
    }
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        init();
        solve();
    }
    return 0;
}

AC源码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int const MAXN = 500000;
int dir[2] = {-1,1};
int rec[MAXN][10],org[10],vis[10],re[10];
int n,num;
bool equ(int a[],int b[])
{
    int i;
    for(i=0; i<n; i++)
        if(a[i]!=b[i])
            return false;
    return true;
}
bool valid(int a[])
{
    int tvis[10];
    memset(tvis,0,sizeof(tvis));
    for(int i=0; i<n; i++){
        if(a[i]>9 || a[i]<1)
            return false;
        for(int j=0; j<2; j++){
        if(a[i]==1 && ((a[i+dir[j]]==3&&tvis[2]==0) || (a[i+dir[j]]==9&&tvis[5]==0) || (a[i+dir[j]]==7&&tvis[4]==0)))
            return false;
        if(a[i]==2 && ((a[i+dir[j]]==8&&tvis[5]==0)))
            return false;
        if(a[i]==3 && ((a[i+dir[j]]==7&&tvis[5]==0) || (a[i+dir[j]]==9&&tvis[6]==0)))
            return false;
        if(a[i]==4 && ((a[i+dir[j]]==6&&tvis[5]==0)))
            return false;
        if(a[i]==7 && ((a[i+dir[j]]==9&&tvis[8]==0)))
            return false;
        }
        tvis[a[i]] = 1;
    }
//    puts("sdas\n");
    return true;
}
void init()
{
    memset(vis,0,sizeof(vis));
    num = 0;
    int i;
    scanf("%d",&n);
    for(i=0; i<n; i++)
        scanf("%d",&org[i]);
    sort(org,org+n);
}
void dfs(int cnt)
{
    int i;
    if(cnt == n+1){
        if(valid(re) && (num==0 || (num>0 && !equ(re,rec[num-1])))){
            for(i=0; i<n; i++)
                rec[num][i] = re[i];
//            printf("num = %d\n",num);
            num++;
        }
        return;
    }
    for(i=0; i<n; i++){
        int t = org[i];
        if(vis[t]==0){
            vis[t] = 1;
            re[cnt-1] = t;
            dfs(cnt+1);
            vis[t] = 0;
        }
    }
}
void solve()
{
    dfs(1);
    printf("%d\n",num);
    int i,j;
//    printf("%d\n",num);
    for(i=0; i<num; i++){
        int f = 1;
//        puts("dasda\n");
        for(j=0; j<n; j++){
            if(f)   f=0;
            else    printf(" ");
            printf("%d",rec[i][j]);
        }
        printf("\n");
    }
}
int main()
{
    int t;  scanf("%d",&t);
    while(t--){
        init();
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值