您的位置:首页 > 其它

noip2011 Mayan游戏

2017-02-25 11:59 330 查看
题目链接:Mayan游戏

这题我首先想到的是bfs,但因为bfs的内存消耗太大,所以只能用dfs。dfs的递归深度只有5层,所以可以考虑。

关于消除方块的问题,不能找到3个相同的方块就消除,如果这样遇到两组共一个方块的就会出错(如题图5)。所以,必需把所有可以消除的方块都先找出来,再消除。因为可能存在连着消除的情况,所以外层要加一个循环。

关于方块下落,最开始交换完就下落一次,在删除方块的过程中,每删除一轮(最外层循环一次)就下落一次。

关于复习运算符重载:

写在结构体内部:

    函数的()与{}之间要加上const,只需传和当前结构体变量运算的那个参数够了(如重载x<y时只用传y)。

    例:

bool operator < (const point& yy) const {
if(x<yy.x) return true;
if(x==yy.x&&y<yy.y) return true;
return false;
}

写在结构体外:
    函数的()与{}之间不加const,运算所需的所有参数都得传(如重载x<y时x,y都要传)。

    例:

bool operator < (const point& xx,const point& yy){
if(xx.x<yy.x) return true;
if(xx.x==yy.x&&xx.y<yy.y) return true;
return false;
}

关于dfs判重;

要注意某一种情况在比当前层数深的地方出现后,在当前情况中还是可以用的,不能在判重中将其去掉。

关于dfs减枝:

1、两个空格不交换。

2、点x和点y交换与点y和点x交换无区别,所以根据优先级关系只考虑像右边交换的情况。而当某个点左边为0时要考虑像左交换。

3、在某种情况下,如果某一种颜色的数量等于1或2,则无论如何这种颜色都不会被消除。

4、如果两个方块颜色相同,不交换。

代码:

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<cstring>
using namespace std;

#define n 5
#define m 7

int c;

struct G {
int a[10][10];
int step;
bool empty() {
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
if(a[i][j]!=0)
return false;
}
}
return true;
}
bool operator < (const G& yy) const {
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
if(a[i][j]<yy.a[i][j]) return true;
if(a[i][j]>yy.a[i][j]) return false;
}
}
return false;
}
};

struct point {
int x,y,g;
point() {}
point(int xx,int yy,int gg) {
x=xx,y=yy,g=gg;
}
bool operator < (const point& yy) const {
if(x<yy.x) return true;
if(x==yy.x&&y<yy.y) return true;
return false;
}
bool operator == (const point& yy) const {
if(x==yy.x&&y==yy.y&&g==yy.g) return true;
return false;
}
};
point move[10];

void Swap(int& x,int& y) {
int t=x;
x=y;
y=t;
return ;
}

void drop(G& x) {
for(int i=1; i<=n; i++) {
for(int j=m; j>=1; j--) {
if(x.a[i][j]==0) {
for(int k=j; k<=m; k++) {
x.a[i][k]=x.a[i][k+1];
}
}
}
}

bool flag1;
do {
flag1=false;
set<point> Set;
for(int i=1; i<=n; i++) {
for(int j=1; j<=m-2; j++) {
if(x.a[i][j]!=0&&x.a[i][j]==x.a[i][j-1]&&x.a[i][j]==x.a[i][j-2]) {
Set.insert(point(i,j,0));
Set.insert(point(i,j-1,0));
Set.insert(point(i,j-2,0));
flag1=true;
}
}
}
for(int i=3; i<=n; i++) {
for(int j=1; j<=m; j++) {
if(x.a[i][j]!=0&&x.a[i][j]==x.a[i-1][j]&&x.a[i][j]==x.a[i-2][j]) {
Set.insert(point(i,j,0));
Set.insert(point(i-1,j,0));
Set.insert(point(i-2,j,0));
flag1=true;
}
}
}
for(set<point>::iterator it=Set.begin(); it!=Set.end(); it++) {
x.a[(*it).x][(*it).y]=0;
}
for(int i=1; i<=n; i++) {
for(int j=m; j>=1; j--) {
if(x.a[i][j]==0) {
for(int k=j; k<=m; k++) {
x.a[i][k]=x.a[i][k+1];
}
}
}
}
} while(flag1);

return ;
}

bool flag=false;
map<G,bool> mp;
void dfs(G x) {
drop(x);
if(x.step>=c) {
if(x.empty()) {
for(int i=0; i<c; i++) {
printf("%d %d %d\n",move[i].x-1,move[i].y-1,move[i].g);
}
flag=true;
}
return ;
}
int scolor[11]={0};
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scolor[x.a[i][j]]++;
}
}
for(int i=1;i<=9;i++){
if(scolor[i]==1||scolor[i]==2) return ;
}

int t=x.step;
x.step=0;
if(mp.count(x)&&mp[x]==true) return ;
mp[x]=true;
x.step=t;

for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
if(x.a[i][j]==0) continue;
G y=x;
if(i+1<=n&&y.a[i][j]!=y.a[i+1][j]) {
move[x.step]=point(i,j,1);
swap(y.a[i][j],y.a[i+1][j]);
y.step++;
dfs(y);
if(flag==true) return ;
}
y=x;
if(i-1>=1&&y.a[i-1][j]==0) {
move[x.step]=point(i,j,-1);
swap(y.a[i][j],y.a[i-1][j]);
y.step++;
dfs(y);
if(flag==true) return ;
}

}
}

mp[x]=false;
return;

}

int main() {
scanf("%d",&c);
G g;
memset(g.a,0,sizeof(g.a));
g.step=0;
for(int i=1; i<=n; i++) {
int x=1;
for(int j=1; x!=0; j++) {
scanf("%d",&x);
g.a[i][j]=x;
}
}
g.step=0;
dfs(g);
if(flag==false) printf("-1");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: