bzoj 4111: [Wf2015]Keyboarding

傻逼广搜,我却想不出来.
f[i][j][k]表示位置ij,打完第k个字母的最少步骤,然后这个题卡内存,用动态内存或者压着内存开数组.
以后如果再看到网格图的题,要想到与每个点连边的只有4个.
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md
using namespace std;
struct PP { int x,y;} a[55][55][4];
struct QQ { int x,y,k,dep;};
queue<QQ> q;
int T[55][55];
bool vis[55][55][10010];
char s[55][55],st[10010];
int n,m,L;
int bfs()
{
    for (int i=1;i<=n;i++)
      for (int j=1;j<=m;j++)
      {
        T[i][j]=0;
        for (int k=i-1;k;k--)
          if (s[k][j]!=s[i][j])
          {
            a[i][j][T[i][j]++]=(PP){k,j};
            break;
          }
        for (int k=i+1;k<=n;k++)
          if (s[k][j]!=s[i][j])
          {
            a[i][j][T[i][j]++]=(PP){k,j};
            break;
          }
        for (int k=j-1;k;k--)
          if (s[i][k]!=s[i][j])
          {
            a[i][j][T[i][j]++]=(PP){i,k};
            break;
          }
        for (int k=j+1;k<=m;k++)
          if (s[i][k]!=s[i][j])
          {
            a[i][j][T[i][j]++]=(PP){i,k};
            break;
          }
      }
    vis[1][1][0]=1; q.push((QQ){1,1,0,0});
    while (!q.empty())
    {
        QQ d=q.front(); int x=d.x,y=d.y,k=d.k,dep=d.dep;
        q.pop();
        if (s[x][y]==st[k+1]&&!vis[x][y][k+1])
        {
            vis[x][y][k+1]=1;
            if (k+1==L) return dep+1;
            q.push((QQ){x,y,k+1,dep+1});
        }
        else
        {
            for (int t=0;t<T[x][y];t++)
            {
                int i=a[x][y][t].x,j=a[x][y][t].y;
                if (!vis[i][j][k])
                {
                    vis[i][j][k]=1;
                    q.push((QQ){i,j,k,dep+1});
                }
            }
        }
    }
    return -1;
}
 
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
      scanf("%s",s[i]+1);
    scanf("%s",st+1);
    L=strlen(st+1); st[++L]='*';
    printf("%d\n",bfs());
    return 0;
}



你可能感兴趣的:(bzoj 4111: [Wf2015]Keyboarding)