zoukankan      html  css  js  c++  java
  • 洛谷 1312 Mayan游戏——暴搜+剪枝

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

    自己写了很久。又T又WA的。

    发现对题理解有误。改完后应该只有T了,但还是T的。

    自己写了许多剪枝,很鸡肋。

    然后去看Zinn的题解。

    重要剪枝:交换的话只从左向右即可!!!向左的只能是空格。两个颜色相同的话就不要换了!(虽然可能需要故意浪费步数?)

    然后就变得非常快。但WA了1个点。去掉自以为等价的那个地方就能了,而且好像还变快了?不知为何。该处见注释。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=8,K=15;
    int n,sta[N][5],a[N][N][N],cnt,ct[K],sum,mx;
    int xx[5]={-1,0,0,1},yy[5]={0,-1,1,0};
    bool vis[N][N],eflag;
    void dfs(int cr,int x,int y,int fx)
    {
      cnt++;vis[x][y]=1;
      int tx=x+xx[fx],ty=y+yy[fx];
      if(!vis[tx][ty]&&a[cr][tx][ty]==a[cr][x][y])
        dfs(cr,tx,ty,fx);
    }
    void cz(int cr,int x,int y)
    {
      
      if(x>1&&a[cr][x-1][y]==a[cr][x][y]&&a[cr][x-2][y]==a[cr][x][y])
        dfs(cr,x,y,0);
      if(y>1&&a[cr][x][y-1]==a[cr][x][y]&&a[cr][x][y-2]==a[cr][x][y])
        dfs(cr,x,y,1);
      //上面两个去掉会错?//去掉上面还会变慢? 
      if(x<3&&a[cr][x+1][y]==a[cr][x][y]&&a[cr][x+2][y]==a[cr][x][y])
        dfs(cr,x,y,3);
      if(y<5&&a[cr][x][y+1]==a[cr][x][y]&&a[cr][x][y+2]==a[cr][x][y])
        dfs(cr,x,y,2);
    }
    void xc(int cr)
    {
      int tmp[N][N]={0};
      for(int i=0;i<=4;i++)
        {
          int p0=0;
          for(int j=0;j<=6;j++)
        {
          while(p0<6&&vis[i][p0])p0++;
          if(vis[i][p0]||!a[cr][i][p0])break;
          tmp[i][j]=a[cr][i][p0];p0++;
        }
        }
      memcpy(a[cr],tmp,sizeof tmp);
    }
    void clear(int cr)
    {
      while(1)
        {
          memset(vis,0,sizeof vis); cnt=0;
          for(int i=0;i<=4;i++)
        for(int j=0;j<=6&&a[cr][i][j];j++)
          if(!vis[i][j])cz(cr,i,j);
          if(!cnt)break; xc(cr); sum-=cnt;
        }
    }
    void calc(int cr,int x,int y,int op)
    {
      memcpy(a[cr],a[cr-1],sizeof a[cr-1]);
      if(a[cr][x+op][y])
        {
          if(a[cr][x][y]==a[cr][x+op][y])return;
          swap(a[cr][x][y],a[cr][x+op][y]);
          clear(cr);  return;
        }
      else
        {
          for(int i=0;i<=6;i++)
        if(!a[cr][x+op][i])
          {a[cr][x+op][i]=a[cr][x][y];break;}
          for(int i=y;i<=6;i++)a[cr][x][i]=a[cr][x][i+1];
          clear(cr);  return;
        }
    }
    bool pan(int cr)
    {
      memset(ct,0,sizeof ct);
      for(int i=0;i<=4;i++)
        for(int j=0;j<=6&&a[cr][i][j];j++)
          ct[a[cr][i][j]]++;
      for(int i=1;i<=mx;i++)if(ct[i]==1||ct[i]==2)return false;
      return true;
    }
    void solve(int cr)
    {
      if(cr>n)
        {
          eflag=!sum; return;
        }
      int ysum=sum;
      for(int i=0;i<=4;i++)
        for(int j=0;j<=6&&a[cr-1][i][j];j++)
          {
        if(i<4&&a[cr-1][i][j]!=a[cr-1][i+1][j])
          {
            calc(cr,i,j,1);
            if(pan(cr))
              {
            sta[cr][0]=i;sta[cr][1]=j;sta[cr][2]=1;
            solve(cr+1); if(eflag)return;
              }
            sum=ysum;
          }
        if(i>0&&!a[cr-1][i-1][j])
          {
            calc(cr,i,j,-1);
            if(pan(cr))
              {
            sta[cr][0]=i;sta[cr][1]=j;sta[cr][2]=-1;
            solve(cr+1); if(eflag)return;
              }
            sum=ysum;
          }
          }
    }
    int main()
    {
      scanf("%d",&n);
      for(int i=0;i<=4;i++)
        for(int j=0;j<=7;j++)//7
          {
        scanf("%d",&a[0][i][j]);
        if(!a[0][i][j])break;
        ct[a[0][i][j]]++; sum++; mx=max(mx,a[0][i][j]);
          }
      if(!pan(0)){puts("-1");return 0;}
    
      solve(1);
      if(eflag)
        {
          for(int i=1;i<=n;i++)
        printf("%d %d %d
    ",sta[i][0],sta[i][1],sta[i][2]);
        }
      else puts("-1");
      return 0;
    }
  • 相关阅读:
    完整约束二(学习笔记)
    完整约束一(学习笔记)
    表的创建与管理二(学习笔记)
    闪回技术(学习笔记)
    表的创建与管理一(学习笔记)
    借助AWR报告分析解决oracleCPU过高的问题(转)
    数据的集合运算(学习笔记)
    SQL:1999基本语法(学习笔记)
    表的连接操作(学习笔记)
    多表查询(学习笔记)
  • 原文地址:https://www.cnblogs.com/Narh/p/9763270.html
Copyright © 2011-2022 走看看