COJ 2498 - Boggle AC自动机+DFS

本文介绍了一种使用AC自动机配合深度优先搜索(DFS)解决在一个4x4字符矩阵中寻找给定单词集合的问题。通过构建AC自动机加速匹配过程,并采用DFS遍历矩阵来查找所有可能的单词,最终计算得分。

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

            题意:

                    给了M个单词(M<=100000,单词长度至多为8,单词仅由大写字母构成)..现在给出若干个4*4的字符矩阵(仅含大写字母)..可以从该矩阵任意一个位置出发..不走重复格子的往周围八个方向前进....并且给出了各种长度所能获得的分数.问能获得的最大分数是多少?.至多能走出多少个单词?走出最长的单词是...

            题解:

                    So easy了. 先把这些单词拿来做一个AC自动机...恶心的是空间..我试了好几次才能不ML又不RE..然后就是DFS了..边走边走AC自动机...值得注意的可能有重复的单词..所以要用数组记录一下..


Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include <stack>
#include<queue>
#include<algorithm>
#include<cmath>
#define oo 1000000007
#define ll long long
#define pi acos(-1.0)
#define MAXN 400005 
using namespace std;    
struct node
{
      int son[26],fail,w;
}P[MAXN];
char ss[8],M[4][4];
bool had[MAXN],used[4][4];
int len[MAXN],T[9]={0,0,0,1,1,2,3,5,11},NUM[MAXN];
int F[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
string s[MAXN]; 
queue<int> Q;
void Build_AC()
{
      int i,h,k;
      for (i=0;i<26;i++)
          if (P[0].son[i]) Q.push(P[0].son[i]);
      while (!Q.empty())
      {
             h=Q.front(),Q.pop(); 
             for (i=0;i<26;i++)
             {
                   k=P[h].fail;
                   while (k && !P[k].son[i]) k=P[k].fail;
                   P[P[h].son[i]].fail=P[k].son[i];
                   if (!P[h].son[i]) P[h].son[i]=P[k].son[i];
                               else  Q.push(P[h].son[i]); 
             }
      }     
}
bool cmp(string a,string b)
{
      if (a.length()!=b.length()) return a.length()>b.length();
      return a<b;      
}
void dfs(int y,int x,int h,int step)
{
      int t,k;
      if (step>8 || y<0 || x<0 || y==4 || x==4 || used[y][x]) return; 
      used[y][x]=true;
      k=h=P[h].son[M[y][x]-'A'];
      while (k) had[P[k].w]=true,k=P[k].fail;
      for (t=0;t<8;t++) 
          dfs(y+F[t][0],x+F[t][1],h,step+1); 
      used[y][x]=false;
}
int main()
{        
      int n,i,q,j,t,h,x,ans,num;   
      memset(P,0,sizeof(P));
      scanf("%d",&n);
      for (i=1;i<=n;i++) scanf("%s",ss),s[i]=ss;
      sort(s+1,s+1+n,cmp);
      num=0;
      for (t=1;t<=n;t++)
      {
              len[t]=s[t].length(),NUM[t]=h=0;
              for (i=0;i<len[t];i++)
              {
                       x=s[t][i]-'A';
                       if (!P[h].son[x]) P[h].son[x]=++num;
                       h=P[h].son[x];
              }
              if (!P[h].w) P[h].w=t,NUM[t]=1;
                      else NUM[P[h].w]++;
      }
      Build_AC();
      scanf("%d",&q);
      while (q--)
      {
              for (i=0;i<4;i++) scanf("%s",M[i]);     
              memset(had,false,sizeof(had));
              memset(used,false,sizeof(used));
              for (i=0;i<4;i++) 
                 for (j=0;j<4;j++)
                    dfs(i,j,0,1); 
              for (t=1;t<=n;t++) 
                 if (had[t]) break;
              num=ans=0;
              for (i=1;i<=n;i++)
                 if (had[i]) ans+=NUM[i]*T[len[i]],num+=NUM[i];
              printf("%d %s %d\n",ans,s[t].c_str(),num);                 
      }
      return 0;
}


资源下载链接为: https://pan.quark.cn/s/67c535f75d4c 在机器人技术中,轨迹规划是实现机器人从一个位置平稳高效移动到另一个位置的核心环节。本资源提供了一套基于 MATLAB 的机器人轨迹规划程序,涵盖了关节空间和笛卡尔空间两种规划方式。MATLAB 是一种强大的数值计算与可视化工具,凭借其灵活易用的特点,常被用于机器人控制算法的开发与仿真。 关节空间轨迹规划主要关注机器人各关节角度的变化,生成从初始配置到目标配置的连续路径。其关键知识点包括: 关节变量:指机器人各关节的旋转角度或伸缩长度。 运动学逆解:通过数学方法从末端执行器的目标位置反推关节变量。 路径平滑:确保关节变量轨迹连续且无抖动,常用方法有 S 型曲线拟合、多项式插值等。 速度和加速度限制:考虑关节的实际物理限制,确保轨迹在允许的动态范围内。 碰撞避免:在规划过程中避免关节与其他物体发生碰撞。 笛卡尔空间轨迹规划直接处理机器人末端执行器在工作空间中的位置和姿态变化,涉及以下内容: 工作空间:机器人可到达的所有三维空间点的集合。 路径规划:在工作空间中找到一条从起点到终点的无碰撞路径。 障碍物表示:采用二维或三维网格、Voronoi 图、Octree 等数据结构表示工作空间中的障碍物。 轨迹生成:通过样条曲线、直线插值等方法生成平滑路径。 实时更新:在规划过程中实时检测并避开新出现的障碍物。 在 MATLAB 中实现上述规划方法,可以借助其内置函数和工具箱: 优化工具箱:用于解决运动学逆解和路径规划中的优化问题。 Simulink:可视化建模环境,适合构建和仿真复杂的控制系统。 ODE 求解器:如 ode45,用于求解机器人动力学方程和轨迹执行过程中的运动学问题。 在实际应用中,通常会结合关节空间和笛卡尔空间的规划方法。先在关节空间生成平滑轨迹,再通过运动学正解将关节轨迹转换为笛卡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值