Mayan游戏

题目链接:https://www.luogu.org/problemnew/show/P1312

(这道题debug了5天的我简直弱爆了。。。)

首先这道题可以说是十分典型的爆搜题,范围非常小,搜索的思路也比较好想,即枚举每一个点向两个方向走的不同情况,超过了规定了的步数就回溯。

这样的搜索可以得到60或者70分,如果开O2的话就可以A掉了,当然也可以搞一下玄学剪枝(例如用map记录图,在搜的时候如果搜到过的话就剪掉等),由于时间比较紧所以也就没去剪枝。

然后还要注意题目给的优先级,按照这个来搜。

最后就是这个题要把细节处理好,具体看代码吧。

code:

#include
#include
using namespace std;

int n, maps[5][8], d[2]={1, -1}, ans1[6], ans2[6], ans3[6];
bool color[5][8], suc;

bool check() {
    int i, j;
    for (i=0; i<5; i++)
        for (j=0; j<7; j++)
            if (maps[i][j]) return false; 
    return true;
}

void update() {
    int i, j;
    for (i=0; i<5; i++) {
        for (j=0; j<7; j++) {
            if (j==0 || maps[i][j]==0) continue;
            if (maps[i][j-1]==0) {
                int temp=j-1;
                if (temp-1>=0) {
                    while (maps[i][temp-1]==0) {
                        temp--;
                        if (temp-1<0) break;
                    }
                }
                maps[i][temp]=maps[i][j];
                maps[i][j]=0;
            }
        }
    }
    return ;
}

void ex(int x1, int y1, int x2, int y2) {
    int temp=maps[x1][y1];
    maps[x1][y1]=maps[x2][y2];
    maps[x2][y2]=temp;
    return ;
}

void clear() {
    int i, j;
    for (i=0; i<5; i++) {
        for (j=0; j<7; j++) {
            if (maps[i][j]==0) break;
            if (color[i][j]) maps[i][j]=0;
        }
    }
    update();
    return ;
}

void mark(int x, int r, int l, int flags) {
    int i;
    if (flags==0) for (i=l; i<=r; i++) color[x][i]=true;
    else for (i=l; i<=r; i++) color[i][x]=true;
    return ;
}

bool find_clear() {
    bool flag=false;
    memset(color, false, sizeof(color));
    int i, j, last, cnt;
    for (i=0; i<5; i++) {
        cnt=1, last=-1;
        for (j=0; j<7; j++) {
            if (maps[i][j]==last) cnt++;
            else {
                if (cnt>=3) {
                    flag=true;
                    mark(i, j-1, j-cnt, 0);
                }
                cnt=1;
            }
            last=maps[i][j];
            if (maps[i][j]==0) break;
        }
    }
    for (j=0; j<7; j++) {
        cnt=1, last=-1;
        for (i=0; i<5; i++) {
            if (maps[i][j]==0) {
                last=maps[i][j];
                continue;
            }
            if (maps[i][j]==last) {
                cnt++;
                if (cnt>=3) {
                    if (i+1<5) {
                        if (maps[i+1][j]!=maps[i][j]) {
                            mark(j, i, i-cnt+1, 1);
                            flag=true;
                        }
                    }
                    else {
                        mark(j, i, i-cnt+1, 1);
                        flag=true;
                    }
                }
            }
            else cnt=1;
            last=maps[i][j];
        }
    }
    if (flag) clear();
    return flag;
}

void dfs(int pos) {
    if (pos>n) return ;
    int i, j, k, temp[5][7];
    for (i=0; i<5; i++)
        for (j=0; j<7; j++)
            temp[i][j]=maps[i][j];
    for (i=0; i<5; i++) {
        for (j=0; j<7; j++) {
            if (maps[i][j]==0) break;
            for (k=0; k<2; k++) {
                int di=i+d[k];
                if (di<0 || di>=5) continue;
                if (maps[di][j]==0) {
                    maps[di][j]=maps[i][j];
                    maps[i][j]=0;
                }
                else ex(i, j, di, j);
                update();
                while (find_clear());
                ans1[pos]=i, ans2[pos]=j, ans3[pos]=d[k];
                if (pos==n && check()) {
                    suc=true;
                    return ;
                }
                dfs(pos+1);
                if (suc) return ;
                ans1[pos]=0, ans2[pos]=0, ans3[pos]=0;
                for (int is=0; is<5; is++)
                    for (int js=0; js<7; js++)
                        maps[is][js]=temp[is][js];
            }
        }
    }
    return ;
}

int main() {
    int i, j, x;
    cin >> n;
    for (i=0; i<5; i++) {
        for (j=0; j<8; j++) {
            cin >> x;
            maps[i][j]=x;
            if (x==0) break;
        }
    }
    dfs(1);
    if (!suc) {
        cout << "-1";
        return 0;
    }
    for (i=1; i<=n; i++)
        cout << ans1[i] << " " << ans2[i] << " " << ans3[i] << endl;
    return 0;
}

练习爆搜和代码能力都不错的题目。

你可能感兴趣的:(算法竞赛)