zoukankan      html  css  js  c++  java
  • GCPC 2013_A Boggle DFS+字典树 CSU 1457

    上周比赛的题目,由于那个B题被神编译器的优化功能给卡了,就没动过这个题,其实就是个字典树嘛。当然,由于要在Boggle矩阵里得到初始序列,我还一度有点虚,不知道是用BFS还是DFS,最后发现DFS要好一些,但是会不会超时呢,我就先敲了DFS部分,先在DFS里面输出所有情况,发现总共搜完只有24W+的情况,然后字典树的匹配几乎是常数时间(因为字符串最大长度只有8)。。。所以就试着做了一下,WA了几次,发现是数组开小了,好久没做字典树的题,我只开了节点个数目的数组,这肯定不对啊,最大可能是30W(字符串总数) *8(同上),当然实际也不会打得这么离谱,因为总共才26个字母,重合的几率很大,所以最多开个30W*2其实就够了。

    今天敲字典树之后突然有种想法,发现以前敲这个都是对着模板敲,现在感觉对这个算法已经很理解了,所以我随便自己怎么发挥,没用结构体,没用指针,照样很好的实现了。

    像AC自动机我还是不是特别熟练,但是我觉得再照模板敲肯定学得更慢,学算法,真的不要学形,而是要学神。

    这个题目也有用AC自动机处理的,确实可以优化一些,失败的话,对应DFS回退,然后树上是对应失败节点,不过处理起来要复杂一些。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    char mat[10][10];
    char wlist[400010][10];
    int vis[500010];
    int w,n,inq[10][10];
    char rec[10];
    int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,-1},{-1,1}};
    int cnt,ch[410010][27],val[500010],ids[500010];
    int point[]={0,0,0,1,1,2,3,5,11,11,11};
    int ans_num,ans_point;
    char anschar[10];
    void inserts(char* s,int num)
    {
        int rt=0;
        int len=strlen(s);
        for (int i=0;i<len;i++){
            int k=s[i]-'A';
            if (ch[rt][k]==-1){
                ch[rt][k]=cnt++;
            }
            rt=ch[rt][k];
        }
        val[rt]=point[len];
        ids[rt]=num;
    }
    void solve(char* s)
    {
        int rt=0;
        int len=strlen(s);
        for (int i=0;i<len;i++){
            int k=s[i]-'A';
            if (ch[rt][k]==-1) break;
            rt=ch[rt][k];
        }
        if (val[rt]!=-1 && vis[ids[rt]]==0){
            vis[ids[rt]]=1;
            ans_num++;
            ans_point+=val[rt];
            if (ans_num==1)
                memcpy(anschar,s,10);
            else if (len==strlen(anschar) && strcmp(s,anschar)<0)
                memcpy(anschar,s,10);
            else if (len>strlen(anschar))
                memcpy(anschar,s,10);
        }
    }
    void dfs(int x,int y,int d)
    {
        if (d>8) return;
        rec[d-1]=mat[x][y];
        rec[d]='';
        solve(rec);
        inq[x][y]=1;
        int tmp;
        for (int i=0;i<8;i++){
            int nx=x+dir[i][0];
            int ny=y+dir[i][1];
            if (nx<0 || ny<0 || nx>=4 || ny>=4) continue;
            if (inq[nx][ny]) continue;
            inq[nx][ny]=1;
            dfs(nx,ny,d+1);
            inq[nx][ny]=0;
        }
        inq[x][y]=0;
    }
    int main()
    {
        //freopen("rand.in","r",stdin);
        //freopen("rand.out","w",stdout);
        while (scanf("%d",&w)!=EOF)
        {
    
            memset(ch,-1,sizeof ch);
            memset(val,-1,sizeof val);
            memset(ids,-1,sizeof ids);
            cnt=1;
            for (int i=0;i<w;i++){
                scanf("%s",wlist[i]);
                inserts(wlist[i],i);
            }
            scanf("%d",&n);
            for (int i=0;i<n;i++){
                memset(vis,0,sizeof vis);
                ans_num=ans_point=0;
                for (int j=0;j<4;j++) {scanf("%s",mat[j]);}
                for (int q=0;q<4;q++)
                 for (int k=0;k<4;k++){
                        dfs(q,k,1);
                }
                printf("%d %s %d
    ",ans_point,anschar,ans_num);
            }
    
        }
        return 0;
    }
  • 相关阅读:
    利用游标循环插入数据
    局部临时表
    表值函数
    SQL2000自动备份压缩删除数据库
    insert select、select into 的用法
    判断每个页面是否登以及捕捉页面异常录解决方案
    合并查询结果
    字符串分隔(转自别处)
    生成行号
    C#计算字符串中子串出现次数的另类方法
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3759921.html
Copyright © 2011-2022 走看看