题目描述
小Mirko在圣诞节得到了一个游戏机,这个游戏机既不是PlayStation4,也不是Xbox One,而是Atari 2600。这个游戏机附带了一款免费游戏,游戏的主角站在屏幕底部,屏幕上其余部分分散着各种各样的物体向底部坠落。 更准确的说,屏幕可以表示为一个R行S列排列组成的RX像素网格。主角站在最下面一行的一个像素中,用‘M’标记,其余像素用另外一些符号标记:‘.’(空格)、‘’(炸弹)、‘(’(左括号)或‘)’(右括号)。 主角可以在一次移动中,向左或向右移动一个像素或者不移动,与此同时,其他物体同时向下移动一个像素(可能会从屏幕上消失)。当主人公发现自己和其中一个括号同处一个位置是,我们就拿起那个括号,并将它添加到获得的括号数组的末尾。主角的目标是获得尽可能长的有效括号表达式。 有效括号表达式是通过以下方式归纳定义的: ·“()”是有效表达式 ·如果a是有效表达式,那么“(a)”也是有效表达式。 ·如果a和b都是有效表达式,那么“ab”也是有效表达式。 当主角发现自己同炸弹一个位置或所有物体掉出屏幕时,游戏结束。
输入格式
第一行输入两个正整数R、S(1≤R,S≤300),表示像素格的行列数。 接下来输入一个R行S列的地图,每个格子包含‘M’,‘.’,‘*’,‘(’,‘)’这五种中的一种字符。 数据保证至少可以获得一个有效括号表达式。
输出格式
第一行输出一个数字,表示有效括号表达式的数量。 第二行输出这个括号表达式。如果有多个答案,输出字典序最小的那一个。
样例
样例输入1
5 4
…).
.)(.
(.)*
(.
…M.
样例输出1
4
(())
样例输入2
6 3
)(.
…
(*
)()
().
M…
样例输出2
4
()()
样例输入3
6 3
((.
…
(*
)()
().
M…
样例输出3
2
()
数据范围与提示
第一组样例走法:左、左、右、右 第二组样例走法:不动、不动、不动、右、左 第三组样例走法:不动、不动、右
解题思路
我们可以发现,一个点可以由三个不同状态转移过来,所以,肯定选择DP,搜索的话就不能够标记。
我们先从上往下走。把左括号看作1,右括号看作-1,点就不管它。
定义dp[i][j][k]表示i行j列所组成的式子的差值。这是肯定没有负数存在的。不会存在不合理的转移,我们就保证了组成的式子一定是合理的,最多存在左括号多余。
于是,最长我们求了出来。
然后,我们求序列,原来的定义就反着来,看哪些符合。bfs即可。
但存在一个优先级的问题,我们应该要优先走点,这样左括号就一直留在上面了,字典序较小,然后优先走左括号,最后才走右括号。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
using namespace std;
char mase[305][305];
int val(char s){
if (s == '.')
return 2;
if (s == '(')
return 1;
if (s == ')')
return 0;
}
struct node{
int x,y,len,hop;
node(){};
node(int X,int Y,int H,int L){
x = X,y = Y,len = L,hop = H;
}
bool operator < (const node &a)const {
if (len == a.len)
return val(mase[x][y]) < val(mase[a.x][a.y]);
else
return len < a.len;
}
};
int r,s,sx,sy,dp[305][305][305],mov1[5] = {0,1,0,-1};
string ans;
bool vis[305][305][305];
void bfs(){
priority_queue<node>Q;
vis[sx][sy][0] = 1;
Q.push(node(sx,sy,0,dp[sx][sy][0]));
while (!Q.empty()){
node p = Q.top();
Q.pop();
if (mase[p.x][p.y] == ')' && ans[p.len] == '(')
continue;
if (mase[p.x][p.y] == '(' || mase[p.x][p.y] == ')')
ans[p.len] = mase[p.x][p.y];
if (p.x == 1)
continue;
for (int i = 1;i <= 3;i ++){
int tox = p.x - 1;
int toy = p.y + mov1[i];
if (tox <= 0 || tox > r || toy <= 0 || toy > s || mase[tox][toy] == '*')
continue;
if (mase[p.x][p.y] == '('){
if (!vis[tox][toy][p.hop + 1] && dp[tox][toy][p.hop + 1] == p.len - 1){
vis[tox][toy][p.hop + 1] = 1;
Q.push(node(tox,toy,p.hop + 1,p.len - 1));
}
}
else if (mase[p.x][p.y] == ')'){
if (p.hop >= 1){
if (dp[tox][toy][p.hop - 1] == p.len - 1 && !vis[tox][toy][p.hop - 1]){
vis[tox][toy][p.hop - 1] = 1;
Q.push(node(tox,toy,p.hop - 1,p.len - 1));
}
}
}
else {
if (dp[tox][toy][p.hop] == p.len && !vis[tox][toy][p.hop]){
vis[tox][toy][p.hop] = 1;
Q.push(node(tox,toy,p.hop,p.len));
}
}
}
}
}
int main(){
memset(dp,-1,sizeof(dp));
scanf ("%d%d",&r,&s);
for (int i = 1;i <= r;i ++){
scanf ("
");
for (int j = 1;j <= s;j ++){
scanf ("%c",&mase[i][j]);
if (mase[i][j] == 'M')
sx = i,sy = j;
}
}
for (int i = 1;i <= s;i ++){
if (mase[1][i] == ')')
dp[1][i][1] = 1;
if (mase[1][i] == '.')
dp[1][i][0] = 0;
}
for (int i = 1;i <= r;i ++){
for (int j = 1;j <= s;j ++)
if (mase[i][j] == '*')
dp[i][j][0] = 0;
}
for (int i = 1;i < r;i ++){
for (int j = 1;j <= s;j ++){
for (int k = 0;k <= r / 2;k ++){
if (dp[i][j][k] == -1)
continue;
for (int l = 1;l <= 3;l ++){
int tox = i + 1;
int toy = j + mov1[l];
if (tox <= 0 || tox > r || toy <= 0 || toy > s || mase[tox][toy] == '*')
continue;
if (mase[tox][toy] == '('){
if (k > 0)
dp[tox][toy][k - 1] = max(dp[tox][toy][k - 1],dp[i][j][k] + 1);
}
else if(mase[tox][toy] == ')')
dp[tox][toy][k + 1] = max(dp[tox][toy][k + 1],dp[i][j][k] + 1);
else
dp[tox][toy][k] = max(dp[tox][toy][k],dp[i][j][k]);
}
}
}
}
printf("%d
",dp[sx][sy][0]);
bfs();
for (int i = dp[sx][sy][0];i >= 1;i --)
printf("%c",ans[i]);
}