Walk Through Squares

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 200    Accepted Submission(s): 57

Problem Description

  On the beaming day of 60th anniversary of NJUST, as a military college which was Second Artillery Academy of Harbin Military Engineering Institute before, queue phalanx is a special landscape.
  
  Here is a M*N rectangle, and this one can be divided into M*N squares which are of the same size. As shown in the figure below:
  01--02--03--04
  || || || ||
  05--06--07--08
  || || || ||
  09--10--11--12
  Consequently, we have (M+1)*(N+1) nodes, which are all connected to their adjacent nodes. And actual queue phalanx will go along the edges.
  The ID of the first node,the one in top-left corner,is 1. And the ID increases line by line first ,and then by column in turn ,as shown in the figure above.
  For every node,there are two viable paths:
  (1)go downward, indicated by 'D';
  (2)go right, indicated by 'R';
  The current mission is that, each queue phalanx has to walk from the left-top node No.1 to the right-bottom node whose id is (M+1)*(N+1).
In order to make a more aesthetic marching, each queue phalanx has to conduct two necessary actions. Let's define the action:
  An action is started from a node to go for a specified travel mode.
  So, two actions must show up in the way from 1 to (M+1)*(N+1).

For example, as to a 3*2 rectangle, figure below:
    01--02--03--04
    || || || ||
    05--06--07--08
    || || || ||
    09--10--11--12
  Assume that the two actions are (1)RRD (2)DDR

As a result , there is only one way : RRDDR. Briefly, you can not find another sequence containing these two strings at the same time.
  If given the N, M and two actions, can you calculate the total ways of walking from node No.1 to the right-bottom node ?

 
Input
  The first line contains a number T,(T is about 100, including 90 small test cases and 10 large ones) denoting the number of the test cases.
  For each test cases,the first line contains two positive integers M and N(For large test cases,1<=M,N<=100, and for small ones 1<=M,N<=40). M denotes the row number and N denotes the column number.
  The next two lines each contains a string which contains only 'R' and 'D'. The length of string will not exceed 100. We ensure there are no empty strings and the two strings are different.
 
Output
  For each test cases,print the answer MOD 1000000007 in one line.
 
Sample Input
2
3 2
RRD
DDR
3 2
R
D
 
Sample Output
1
10
 
Source
 
Recommend
liuyiding
 

太伤了。

网络赛的时候没有过这题,都写对了,就是一直WA

比赛结束后问了下世界冠军cxlove,看了一眼发现是建立AC自动机的时候,fail的end要传递下,加一句话就过了,TAT

使用AC自动机+DP。

dp[x][y][i][k] 四维DP,表示R的个数是x,D的个数是y, i是在AC自动机上的节点编号。k 是状态压缩。

 /* ***********************************************
Author :kuangbin
Created Time :2013/9/21 星期六 15:57:51
File Name :2013南京网络赛\1011.cpp
************************************************ */ #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int MOD = 1e9+; int dp[][][][];
int n,m;
//struct Trie
//{
int next[][],fail[],end[];
int root,L;
inline int change(char ch)
{
if(ch == 'R')return ;
else return ;
}
inline int newnode()
{
for(int i = ;i < ;i++)
next[L][i] = -;
end[L++] = ;
return L-;
}
inline void init()
{
L = ;
root = newnode();
}
inline void insert(char buf[],int id)
{
int len = strlen(buf);
int now = root;
for(int i = ;i < len;i++)
{
if(next[now][change(buf[i])] == -)
next[now][change(buf[i])] = newnode();
now = next[now][change(buf[i])];
}
end[now] |= (<<id);
}
inline void build()
{
queue<int>Q;
fail[root] = root;
for(int i = ;i < ;i++)
if(next[root][i] == -)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while( !Q.empty() )
{
int now = Q.front();
Q.pop();
end[now] |= end[fail[now]];
for(int i = ;i < ;i++)
if(next[now][i] == -)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
inline int solve()
{
dp[][][][] = ;
int ret = ; for(int x = ;x <= n;x++)
for(int y = ;y <= m;y++)
for(int i = ;i < L;i++) for(int k = ;k < ;k++) {
if(dp[x][y][i][k] == )continue;
if(x < n)
{
int nxt = next[i][];
dp[x+][y][nxt][k|end[nxt]] += dp[x][y][i][k];
if(dp[x+][y][nxt][k|end[nxt]] >= MOD)
dp[x+][y][nxt][k|end[nxt]] -= MOD;
}
if(y < m)
{
int nxt = next[i][];
dp[x][y+][nxt][k|end[nxt]] += dp[x][y][i][k];
if(dp[x][y+][nxt][k|end[nxt]] >= MOD)
dp[x][y+][nxt][k|end[nxt]] -= MOD;
}
}
for(int i = ;i < L;i++)
{
ret += dp[n][m][i][];
if(ret >= MOD)ret -= MOD;
} return ret; }
//};
//Trie ac;
char str[]; int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for(int i = ;i < ;i++)
{
scanf("%s",str);
insert(str,i);
}
build();
for(int i = ;i <= n;i++)
for(int j = ;j <= m;j++)
for(int x = ; x < L;x++)
for(int y = ;y < ;y++)
dp[i][j][x][y] = ;
printf("%d\n",solve());
}
return ;
}

HDU 4758 Walk Through Squares (2013南京网络赛1011题,AC自动机+DP)的更多相关文章

  1. HDU 4751 Divide Groups (2013南京网络赛1004题,判断二分图)

    Divide Groups Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  2. HDU 4750 Count The Pairs (2013南京网络赛1003题,并查集)

    Count The Pairs Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others ...

  3. HDU 4758——Walk Through Squares——2013 ACM/ICPC Asia Regional Nanjing Online

    与其说这是一次重温AC自动机+dp,倒不如说这是个坑,而且把队友给深坑了. 这个题目都没A得出来,我只觉得我以前的AC自动机的题目都白刷了——深坑啊. 题目的意思是给你两个串,每个串只含有R或者D,要 ...

  4. HDU 4759 Poker Shuffle(2013长春网络赛1001题)

    Poker Shuffle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  5. hdu 4750 Count The Pairs (2013南京网络赛)

    n个点m条无向边的图,对于q个询问,每次查询点对间最小瓶颈路 >=f 的点对有多少. 最小瓶颈路显然在kruskal求得的MST上.而输入保证所有边权唯一,也就是说f[i][j]肯定唯一了. 拿 ...

  6. 2019ICPC南京网络赛A题 The beautiful values of the palace(三维偏序)

    2019ICPC南京网络赛A题 The beautiful values of the palace https://nanti.jisuanke.com/t/41298 Here is a squa ...

  7. HDU 4739 Zhuge Liang's Mines (2013杭州网络赛1002题)

    Zhuge Liang's Mines Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  8. HDU 4763 Theme Section (2013长春网络赛1005,KMP)

    Theme Section Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  9. HDU 4762 Cut the Cake (2013长春网络赛1004题,公式题)

    Cut the Cake Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

随机推荐

  1. CF11D A Simple Task(状压DP)

    \(solution:\) 思路大家应该都懂: 状压DP:\(f[i][j]\),其中 \(i\) 这一维是需要状压的,用来记录19个节点每一个是否已经走过(走过为 \(1\) ,没走为 \(0\) ...

  2. android ViewPager之PagerAdapter中View的重用

    在写PagerAdapter的时候,需要重写instantiateItem(ViewGroup  container ,int position)   此方法中,将需要加载的View,添加到conta ...

  3. CentOS安装SVN客户端(rpm)

    http://mirrors.163.com/centos/6/os/x86_64/Packages/ 1.检查是已经安装了svn: rpm -qa subversion subversion-1.7 ...

  4. linux C守护进程编写

    linux编程-守护进程编写 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待 处理某些发生的事件.守护进程是一种很有用的进程. Linux的大多数服 ...

  5. 微信小程序调用接口返回数据或提交数据

    由于小程序发起网络请求需要通过 wx.request 文档地址 https://mp.weixin.qq.com/debug/wxadoc/dev/api/network-request.html 习 ...

  6. express-partials使用方法

    1.安装express-partials 方法一:运行cmd用npm install express-partials 方法二:在package.json里面的dependencies添加" ...

  7. Java基础84 javaBean规范

    1.javaBean的概述 1.javaBeam(咖啡豆)是一种开发规范,也可以说是一种技术.  2.JavaBean就是一个普通java类,只要符合以下规定才能称作为javaBean:        ...

  8. pyqt5-组件

    组件(widgets)是构建一个应用的基础模块.PyQt5有广泛的各式各样的组件,包含:复选按钮(QCheckBox),切换按钮(ToggleButton),滑块条(QSlider),进度条(Prog ...

  9. .NetCore下 Exceptionless 分布式日志的个性化处理

    Event Type 在Exceptionless中有 Exception .LogMessage.Broken Links .Feature Usages 接下来就这几种类型分别添加日志记录 Exc ...

  10. T-SQL语句1

    一.创建表 1.创建常见表 create table tablename ( Column_name1 dataType, Column_name1 dataType, Column_name1 da ...