改进介绍

对比之前的程序:1.添加了hash去重,减少bfs扩展结点个数,加快了搜索个数,对于任何局面均可在1s内完成搜索。2.改变了对于某一局势的变化方式,从以前的dfs变成了强行模拟每一粒水滴,增加了准确性。

代码:

#include<bits/stdc++.h>
using namespace std;
const int bas = 6;
#define MOD 1000000007
#define mod(x) ((x)%MOD)
typedef long long int qq;
const int e = 17;
int mov[5][2]={{0,0},{1,0},{-1,0},{0,1},{0,-1}};
struct node{
    short x,y;
    int pre;
    node(){};
    node(short xx,short yy,short pp){
        x=xx;
        y=yy;
        pre=pp;
    }
};
vector<node>way;
struct point{
    short a[bas][bas];
    qq hast;
    qq hash(){
        hast=0;
        for(int i=0;i<bas;i++){
            for(int j=0;j<bas;j++){
                hast=hast*e+a[i][j];
            }
        }
        return hast;
    }
    print(){
        for(int i=0;i<bas;i++){
            for(int j=0;j<bas;j++){
                printf("%d",a[i][j]);
            }
            printf("\n");
        }
        printf("----%lld-------\n",hash());
    };
};
map<qq,bool>vis;
queue<point>q;
point input(){
    point ret;
    for(int i=0;i<bas;i++){
        char temp[10];
        scanf("%s",temp);
        for(int j=0;j<bas;j++){
            ret.a[i][j]=temp[j]-'0';
        }
    }
    way.push_back(node(-1,-1,0));
    return ret;
}
/*point boom(point now,int sx,int sy){ now.a[sx][sy]=0; for(int i=1;i<=4;i++){ int x=sx,y=sy; while(x>=0&&x<bas&&y>=0&&y<bas){ x+=mov[i][0]; y+=mov[i][1]; if(now.a[x][y]!=0){ now.a[x][y]++; break; } } if(now.a[x][y]==5) now=boom(now,x,y); } now.hash(); return now; }*/
point boom2(point now,int sx,int sy){
    int num=1;
    int wat[bas][bas][5]={0};
    now.a[sx][sy]=0;
    for(int i=1;i<=4;i++){
        wat[sx][sy][i]++;
    }

    while(num){//每次一步
        /*----------------将已经被击中的泡泡爆炸----------------*/
        for(int i=0;i<bas;i++)for(int j=0;j<bas;j++){
            for(int k=1;k<=4;k++){
                //if(wat[i][j][k]==0)continue;
                if(now.a[i][j]!=0){
                    while(now.a[i][j]<5&&wat[i][j][k]>0){//将当前水滴填充进泡泡
                        now.a[i][j]++;
                        wat[i][j][k]--;
                    }
                    if(now.a[i][j]==5){//当前泡泡爆炸
                        now.a[i][j]=0;
                        for(int kk=1;kk<=4;kk++){
                            wat[i][j][kk]++;
                        }
                    }
                }
            }
        }
        /*-------------所有水滴按照位移向量移动一格-------------------*/
        num=0;
        int temp[bas][bas][5]={0};
        for(int i=0;i<bas;i++)for(int j=0;j<bas;j++){
            for(int k=1;k<=4;k++){
                int x=i+mov[k][0];
                int y=j+mov[k][1];
                if(x<0||x>=bas||y<0||y>=bas)continue;
                temp[x][y][k]+=wat[i][j][k];
                num+=wat[i][j][k];
            }
        }
        for(int i=0;i<bas;i++)for(int j=0;j<bas;j++){
            for(int k=1;k<=4;k++){
                wat[i][j][k]=temp[i][j][k];
            }
        }
    }
    now.hash();
    return now;
}
void bfs(point s){
    int frt=0;
    s.hash();
    q.push(s);
    while(!q.empty()){
        point temp=q.front();
        for(int i=0;i<bas;i++)for(int j=0;j<bas;j++){//扩展新局面
            if(temp.a[i][j]==0)continue;
            temp.a[i][j]++;
            point now;
            if(temp.a[i][j]==5) now=boom2(temp,i,j);
            else now=temp;

            if(vis.count(now.hast)==0){//没出现过的新局面入队
                q.push(now);
                way.push_back(node(i,j,frt));
                vis[now.hast]=1;
            }
            if(now.hast==0)return;
            temp.a[i][j]--;

        }
        q.pop();
        frt++;
    }
}

void output(){
    node now=way[way.size()-1];
    int x[30],y[30],cnt=0;
    while(now.x!=-1&&now.y!=-1){
        x[cnt]=now.x;
        y[cnt]=now.y;
        cnt++;
        now=way[now.pre];
    }
    for(int i=cnt-1;i>=0;i--){
        printf("( %d %d )\n",x[i]+1,y[i]+1);
    }
}
void test(){
    point s=input();
    int x,y;
    while(scanf("%d%d",&x,&y)){
        x--;y--;
        s.a[x][y]++;
        if(s.a[x][y]==5){
            s=boom2(s,x,y);
        }
        s.print();
    }
}
void init(){
    way.clear();
    vis.clear();
    while(!q.empty())q.pop();

}
int main(){
    //test();
    while(1){
        init();
        point s=input();
        bfs(s);
        output();
    }
    return 0;
}
/* 小目标1:完成搜索找到最优策略 √ 小目标2:改成从初始状态生成一个边权图,找到起点s到终点t的最短路径 小目标3:加入图像识别系统,自动将输入图像完成 小目标4:将程序自动加入到页面中自动冲关。 */