#define SOLVERNAME wangyi2
namespace mylib{void SOLVERNAME(void);}
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main(int argc,char *argv[])
{
mylib::SOLVERNAME();
}
namespace mylib
{
class Remove
{
static const int scale=20;
int width,height;
int data[scale][scale];
int sx,sy,ex,ey;
int counter;
void readin()
{
cin>>height>>width;
char temp;
for(int row=0;row<height;row++)
for(int col=0;col<width;col++)
{
cin>>temp;
data[row][col]=((temp=='.')?0:(temp-'A'+1));
}
cin>>sy>>sx>>ey>>ex;
}
bool tryremove()
{
bool flag=false;
vector<int> setx;
vector<int> sety;
for(int row=0;row<height;row++)
{
//先看横线上有没有。
int previous=-1,total=-1;
for(int col=0;col<width;col++)
{
if(data[row][col]==previous)
{
total++;
}
else
{
if(total>=3&&previous>0)
{
flag=true;
for(int x=1;x<=total;x++)
{
setx.push_back(col-x);
sety.push_back(row);
}
}
previous=data[row][col];
total=1;
}
}
if(total>=3&&previous>0)
{
flag=true;
for(int x=1;x<=total;x++)
{
setx.push_back(width-x);
sety.push_back(row);
}
}
}
for(int col=0;col<width;col++)
{
//再看竖线上有没有。
int previous=-1,total=-1;
for(int row=0;row<height;row++)
{
if(data[row][col]==previous)
{
total++;
}
else
{
if(total>=3&&previous>0)
{
flag=true;
for(int x=1;x<=total;x++)
{
setx.push_back(col);
sety.push_back(row-x);
}
}
previous=data[row][col];
total=1;
}
}
if(total>=3&&previous>0)
{
flag=true;
for(int x=1;x<=total;x++)
{
setx.push_back(col);
sety.push_back(height-x);
}
}
}
int lenth=setx.size();
for(int i=0;i<lenth;i++)
{
int x=setx.at(i);
int y=sety.at(i);
if(data[y][x]!=0)
{
counter++;
data[y][x]=0;
}
}
return flag;
}
bool trydown()
{
for(int col=0;col<width;col++)
{
//针对每列进行。
int currow=height-1;
for(int row=height-1;row>=0;row--)
{
if(data[row][col]>0)
data[currow--][col]=data[row][col];
}
for(int row=currow;row>=0;row--)
data[row][col]=0;
}
return false;
}
public:
int getresult()
{
readin();
counter=0;
int temp=data[ey][ex];
data[ey][ex]=data[sy][sx];
data[sy][sx]=temp;
while(tryremove())
trydown();
return counter;
}
void debug()
{
for(int row=0;row<height;row++)
{
for(int col=0;col<width;col++)
cout<<data[row][col]<<"\t";
cout<<endl;
}
cout<<endl;
}
};
void wangyi2()
{
int count;
cin>>count;
Remove* re=new Remove();
for(int i=0;i<count;i++)
cout<<re->getresult()<<endl;
delete re;
}
}
消消看问题的流程就是:尝试消去方块,如果不能消去则结束,否则执行方块下降过程,然后再次尝试消去。
方块下降的时候注意方向,因为我把y轴定义为垂直方向,且是从上到下,则下降算法在针对每列进行时,y坐标从height-1开始减小。用currow记录着下一个可以下降的位置,然后将遇到的方块放到此处,注意那个被移动的方块原位置处要清零,代表空。
方块消去的时候,按照行与列来逐一寻找,但注意在找到一个长度大于或等于3的连续块时不能立刻消去,而是要保存下存,因为一个行消去与列消去可能共用了其中的某些点,如果立刻消去的话会导致相关的另一个可消除行或列不能消除。最后把这些可消除点一一置0,但注意这些待消去点可能有重复,同时要增加对消去块数目的计数(counter成员)。
最后,在行或列上寻求可消除序列时,注意要尽可能找最长的序列,即遇到了一个和之前不一样的块时才去计算前面是否形成了一个可消除序列。
还要注意题中输入的坐标是先垂直方向坐标,后水平方向坐标,分别对应这我这里的y与x,即数组data的第一维与第二维。