zoukankan      html  css  js  c++  java
  • Mayan游戏

    题面:https://www.luogu.org/problemnew/show/P1312

    搜索无疑

    剪枝:

    1.交换的两个块颜色相同,跳过。

    2.如果一个块的左边有块,那么这个块左移不优。

    因为左边的这个块右移效果相同,但是字典序更优。

    我的剪枝:
    1.如果一个颜色的块>=1且<=2,return

    2.如果一种颜色的相邻距离-1的和>剩下步数,return(因为,一次操作,最多一个块进行靠拢)

    3.哈希表判重

    代码:

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int mod=1e9+7;
    const int P=16;
    const int mo=1e5;
    const int M=800000+5;
    int mp[10][8];
    int n;
    bool kp;
    int up=0;
    struct ha{
        int cnt;
        ll val[M],nxt[M];
        int hd[mo];
        void ins(ll x){
            int pos=x%mo;
            val[++cnt]=x;nxt[cnt]=hd[pos];hd[pos]=cnt;
        }
        bool query(ll x){
            int pos=x%mo;
            for(int i=hd[pos];i;i=nxt[i]){
                if(val[i]==x) return true;
            }return false;
        }
    }HA;
    void down(){
        for(int j=1;j<=5;j++){
            int top=1;
            for(int i=1;i<=7;i++){
                if(mp[i][j]){
                    if(top!=i) mp[top][j]=mp[i][j],mp[i][j]=0;
                    ++top;
                }
            }
        }
    }
    bool die[10][8];
    bool kil(bool oo){
        memset(die,0,sizeof die);
        for(int j=1;j<=5;j++){
            int co=0;
            int cnt=0;
            int st=0;
            for(int i=1;i<=7;i++){
                co=mp[i][j];
                st=i;
                cnt=0;
                while(i<=7&&mp[i][j]==co) cnt++,i++;
                i--;
                if(cnt>=3&&co){
                    for(int k=st;k<=i;k++) die[k][j]=1;
                }
            }
        }
        for(int i=1;i<=7;i++){
            int co=0;
            int cnt=0;
            int st=0;
            for(int j=1;j<=5;j++){
                co=mp[i][j];
                st=j;
                cnt=0;
                while(j<=5&&mp[i][j]==co) cnt++,j++;
                j--;
                if(cnt>=3&&co){
                    for(int k=st;k<=j;k++) die[i][k]=1;
                }
            }
        }
        bool over=false;
        for(int i=1;i<=7;i++){
            for(int j=1;j<=5;j++){
                if(die[i][j]){
                    over=true;
                    mp[i][j]=0;
                }
            }
        }
        if(over) return true;
        return false;
    }
    struct node{
        int x,y,d;
    }sta[10],ans[10];
    int top;
    bool fl;
    int las[P];
    int nd[P];
    int num[P];
    int che(int re){
        memset(las,0,sizeof las);
        memset(nd,0,sizeof nd);
        memset(num,0,sizeof num);
        ll hsh=re;
        int sz=0;
        for(int j=1;j<=5;j++){
            for(int i=1;i<=7;i++){
                hsh=(hsh*P+mp[i][j])%mod;
                if(mp[i][j]==0) break;
                sz++;
                num[mp[i][j]]++;
                if(las[mp[i][j]]){
                    nd[mp[i][j]]+=j-las[mp[i][j]]-1;
                }
                las[mp[i][j]]=j;
            }
        }
        if(sz==0) return 2;
        if(HA.query(hsh)) return 0;
        for(int c=1;c<=up;c++){
            if(nd[c]>re) return 0;
            if(num[c]==1||num[c]==2) return 0;
        }
        HA.ins(hsh);
        return 1;
    }
    bool cmp(){
        for(int i=1;i<=n;i++){
            if(sta[i].y<ans[i].y) return true;
            if(sta[i].y>ans[i].y) return false;
            if(sta[i].x<ans[i].x) return true;
            if(sta[i].x>ans[i].x) return false;
            if(sta[i].d>ans[i].d) return true;
            if(sta[i].d<ans[i].d) return false;
        }
        return false;
    }
    int shit=0;
    void dfs(int now){
        if(now==n+1){
            if(che(0)==2){
                if(!fl){
                    fl=true;
                    for(int i=1;i<=n;i++){
                        ans[i]=sta[i];
                    }
                }
                else if(cmp()){
                    for(int i=1;i<=n;i++){
                        ans[i]=sta[i];
                    }
                }
            }    
            return;    
        }
        if(!che(n-now+1)) return;
        int tmp[10][8];
        memcpy(tmp,mp,sizeof mp);
        for(int j=1;j<=5;j++){
            for(int i=1;i<=7;i++){
                if(mp[i][j]){
                    if(j!=1&&mp[i][j]!=mp[i][j-1]&&(!mp[i][j-1])){
                        swap(mp[i][j],mp[i][j-1]);
                        sta[now].x=i,sta[now].y=j;
                        sta[now].d=-1;
                        while(1){
                            down();
                            if(!kil(kp)) break;
                        }
                        dfs(now+1);
                        sta[now].x=sta[now].y=sta[now].d=0;
                        memcpy(mp,tmp,sizeof tmp);
                    }
                    
                    if(j!=5&&mp[i][j]!=mp[i][j+1]){
                        swap(mp[i][j],mp[i][j+1]);
                        sta[now].x=i,sta[now].y=j;
                        sta[now].d=1;
                        while(1){
                            down();
                            if(!kil(kp)) break;
                        }
                        dfs(now+1);
                        sta[now].x=sta[now].y=sta[now].d=0;
                        memcpy(mp,tmp,sizeof tmp);
                    }
                    
                }
                else break;
                
            }
        }
    }
    int main(){
        scanf("%d",&n);
        for(int j=1;j<=5;j++){
            int lp=0;
            int t;
            while(1){
                scanf("%d",&t);
                up=max(up,t);
                if(t==0) break;
                mp[++lp][j]=t;
            }
        }
        fl=false;
        dfs(1);
        if(!fl){
            printf("-1");return 0;
        }
        for(int i=1;i<=n;i++){
            printf("%d %d %d
    ",ans[i].y-1,ans[i].x-1,ans[i].d);
        }
        return 0;
    }

     错误点:

    1.消除的时候中途出锅

    2.HA表,必须再加上剩余步数作为hash值,否则会把正解冲突。

    3.关键字的比较!我用的是x,y翻过来的情况,所以,程序中,应该先比较y,再比较x。

    总结:
    搜索这种东西,细节就是极多,写的时候一定要头脑清醒,不可大意。

    而且,过多的递归,很难调试。

  • 相关阅读:
    LeetCode
    (六)6.5 Neurons Networks Implements of Sparse Autoencoder
    (六)6.4 Neurons Networks Autoencoders and Sparsity
    (六) 6.3 Neurons Networks Gradient Checking
    opencv::调整图像亮度与对比度
    opencv::两张图片的线性融合
    opencv::源码编译
    日志::spdlog
    std::is_same
    json::rapidjson工具
  • 原文地址:https://www.cnblogs.com/Miracevin/p/9779642.html
Copyright © 2011-2022 走看看