Letter Grid(动规)

Consider the following letter grid:

E

R

A

T

A

T

S

R

A

U

T

U

There are 7 ways to read the word TARTU from the grid:

E

R

A

T

A

T

S

R

A

U

T

U

 

E

R

A

T

A

T

S

R

A

U

T

U

 

E

R

A

T

A

T

S

R

A

U

T

U

 

E

R

A

T

A

T

S

R

A

U

T

U

 

E

R

A

T

A

T

S

R

A

U

T

U

 

E

R

A

T

A

T

S

R

A

U

T

U

 

E

R

A

T

A

T

S

R

A

U

T

U

 

 

Given a letter grid and a word, your task is to determine the number of ways the word can be read from the grid. The first letter of the word can be in any cell of the grid, and after each letter, the next letter has to be in one of the neighbour cells (horizontally, vertically or diagonally). A cell can be used multiple times when reading the word.

Input Data

Each test case contains three integers: H (1 ≤ H ≤ 200), the height of the grid, W (1 ≤ W ≤ 200), the width of the grid, and L (1 ≤ L ≤ 100), the length of the word. The following H lines each containing W letters describe the grid. The last line containing L letters describes the word. All letters in the grid and in the word are uppercase English letters (A...Z).

Output Data

For each case, output only line contained one integer: the number of ways the word can be read from the grid. You may assume that the answer is always at most 1018.

Examples

in

out

3 4 5
ERAT
ATSR
AUTU
TARTU

2 2 10
AA
AA
AAAAAAAAAA

7

78732

 

 这是一道动态规划的题:

即待匹配的字符串,每一个字符依次代表一种状态,最后一个字符即代表最后的状态。

eg.

    第一个例子:

 TARTU

T:                  A:                 R:                     T:                    U:

0 0 0 1           0 0 2 0          0 3 0 0              0 0 0 2             0 0 0 0

0 1 0 0           1 0 0 0          0 0 0 2              0 3 0 0             0 0 0 0

0 0 1 0           0 0 0 0          0 0 0 0              0 0 2 0             0 5 0 2

其中每一个不为零的位置,代表到达对应字符的方法数。

后一种字符的方法数,为其前一种字符的得方法数在相应位置的叠加。

 

代码实现:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
char a[201][201];
long long sum[201][201][101];
char ex[101];
int strx[8]={0,0,-1,1,1,-1,1,-1};
int stry[8]={1,-1,0,0,1,-1,-1,1};
int main(){
    int n,m,le;
    while(scanf("%d%d%d",&n,&m,&le)!=EOF){
        memset(sum,0,sizeof(sum));
        int times=0;
        for(int i=0;i<n;i++){
                scanf("%s",a[i]);
                        }
        scanf("%s",ex);
        for(int j=0;j<n;j++){
                for(int k=0;k<m;k++){
                        if(a[j][k]==ex[0]){
                                times++;
                                sum[j][k][0]=1;
                                }
                                }
                                }
        if(le==1){
              cout<<times<<endl;
              continue;
              }
        long long resum=0;
        for(int g=1;g<le;g++){
                long long res;
                for(int f=0;f<n;f++){
                        for(int d=0;d<m;d++){
                                if(a[f][d]==ex[g]){
                                      res=0;
                                      for(int s=0;s<8;s++){
                                              int temp1=f+strx[s];
                                              int temp2=d+stry[s];
                                              if(temp1>=0&&temp1<n&&temp2>=0&&temp2<m){
                                                       if(a[temp1][temp2]==ex[g-1]){
                                                              res+=sum[temp1][temp2][g-1];
                                                              }
                                                              }
                                                              }
                                      sum[f][d][g]=res;
                                      if(g==le-1)
                                          resum+=res;
                                      }
                                      }
                                      }
                                      }
        cout<<resum<<endl;
        }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值