2 条题解

  • 0
    @ 2025-10-8 17:04:11

    B30 IDA*算法 The Rotation Game

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int op[8][7]={ //8个操作的格子编号
        {0,2,6,11,15,20,22},   //A
        {1,3,8,12,17,21,23},   //B
        {10,9,8,7,6,5,4},      //C
        {19,18,17,16,15,14,13},//D
        {23,21,17,12,8,3,1},   //E
        {22,20,15,11,6,2,0},   //F
        {13,14,15,16,17,18,19},//G
        {4,5,6,7,8,9,10}       //H
    };
    int cent[8]={6,7,8,11,12,15,16,17}; //中心
    int iop[8]={5,4,7,6,1,0,3,2}; //逆操作
    int dep,a[24],path[100];
    
    void operate(int x){ //第x种操作
      int t=a[op[x][0]];
      for(int i=0; i<6; i++)
        a[op[x][i]]=a[op[x][i+1]];
      a[op[x][6]]=t;
    }
    bool check(){ //中心数字是否相同
      for(int i=1; i<8; i++)
        if(a[cent[i]]!=a[cent[0]]) return False;
      return True; 
    }
    int f(){ //估价函数: f=8-k
      static int cnt[4]; memset(cnt,0,sizeof cnt);
      for(int i=0; i<8; i++) cnt[a[cent[i]]]++;
      int k=0; //中心数字最多的出现次数为k
      for(int i=1; i<=3; i++) k=max(k,cnt[i]);
      return 8-k; //换掉不同数字,至少操作8-k次
    }
    //第u层, 上一次操作为last
    bool dfs(int u,int last){
      if(u+f()>dep) return False;
      if(check()) return True;
      for(int i=0; i<8; i++){
        if(iop[i]==last) continue;
        operate(i);      //操作一次
        path[ u ]=i;
        if(dfs(u+1,i)) return True;
        operate(iop[i]); //恢复现场
      }
      return False;
    }
    int main(){
      while(scanf("%d",&a[0]),a[0]){
        for(int i=1;i<24;i++)scanf("%d",&a[i]);
        for(dep=0; !dfs(0,-1); dep++);
        if(!dep) printf("No moves needed");
        for(int i=0; i<dep; i++) 
          printf("%c",'A'+path[i]);
        printf("\n%d\n",a[6]);
      }
    }
    

    zjj代码:

    #include<cstdio>
    #include<cstring>
    using namespace std;
    inline int mymax(int x,int y){return x>y?x:y;}
    inline int mymin(int x,int y){return x<y?x:y;}
    int a[30];
    inline bool pd(){return (a[7]==a[8] && a[8]==a[9] && a[9]==a[12] && a[12]==a[13] && a[13]==a[16] && a[16]==a[17] && a[17]==a[18]);}
    int fuck[]={0,7,8,9,12,...,17,18};
    inline int check()
    {
        int cnt=100;
        //左右第一个
        for(int t=1;t<=3;t++)
        {
            int tot=0;
            for(int i=1;i<=8;i++)tot+=(a[fuck[i]]!=t);
            cnt=mymin(cnt,tot);
        }
        return cnt;
    }
    inline void heng(int l,int r,int type)
    {
        if(!type)//左拉 
        {
            int x=a[l];
            for(int i=l;i<r;i++)a[i]=a[i+1];
            a[r]=x;
        }
        else//右拉 
        {
            int x=a[r];
            for(int i=r;i>l;i--)a[i]=a[i-1];
            a[l]=x;
        }
    }
    int li[2][8]={{0,1,3,7,12,16,21,23},{0,2,4,9,13,18,22,24}};
    inline void lie(int *list,int type)
    {
        if(!type)//上拉 
        {
            int x=a[list[1]];
            for(int i=1;i<7;i++)a[list[i]]=a[list[i+1]];
            a[list[7]]=x;
        }
        else//下拉 
        {
            int x=a[list[7]];
            for(int i=7;i>=2;i--)a[list[i]]=a[list[i-1]];
            a[list[1]]=x;
        }
    • 0
      @ 2025-10-8 17:03:29

      B30 IDA*算法 The Rotation Game

      #include <cstdio>
      #include <cstring>
      #include <iostream>
      #include <algorithm>
      using namespace std;
      
      int op[8][7]={ //8个操作的格子编号
          {0,2,6,11,15,20,22},   //A
          {1,3,8,12,17,21,23},   //B
          {10,9,8,7,6,5,4},      //C
          {19,18,17,16,15,14,13},//D
          {23,21,17,12,8,3,1},   //E
          {22,20,15,11,6,2,0},   //F
          {13,14,15,16,17,18,19},//G
          {4,5,6,7,8,9,10}       //H
      };
      int cent[8]={6,7,8,11,12,15,16,17}; //中心
      int iop[8]={5,4,7,6,1,0,3,2}; //逆操作
      int dep,a[24],path[100];
      
      void operate(int x){ //第x种操作
        int t=a[op[x][0]];
        for(int i=0; i<6; i++)
          a[op[x][i]]=a[op[x][i+1]];
        a[op[x][6]]=t;
      }
      bool check(){ //中心数字是否相同
        for(int i=1; i<8; i++)
          if(a[cent[i]]!=a[cent[0]]) return False;
        return True; 
      }
      int f(){ //估价函数: f=8-k
        static int cnt[4]; memset(cnt,0,sizeof cnt);
        for(int i=0; i<8; i++) cnt[a[cent[i]]]++;
        int k=0; //中心数字最多的出现次数为k
        for(int i=1; i<=3; i++) k=max(k,cnt[i]);
        return 8-k; //换掉不同数字,至少操作8-k次
      }
      //第u层, 上一次操作为last
      bool dfs(int u,int last){
        if(u+f()>dep) return False;
        if(check()) return True;
        for(int i=0; i<8; i++){
          if(iop[i]==last) continue;
          operate(i);      //操作一次
          path[ u ]=i;
          if(dfs(u+1,i)) return True;
          operate(iop[i]); //恢复现场
        }
        return False;
      }
      int main(){
        while(scanf("%d",&a[0]),a[0]){
          for(int i=1;i<24;i++)scanf("%d",&a[i]);
          for(dep=0; !dfs(0,-1); dep++);
          if(!dep) printf("No moves needed");
          for(int i=0; i<dep; i++) 
            printf("%c",'A'+path[i]);
          printf("\n%d\n",a[6]);
        }
      }

      zjj代码:
      #include<cstdio>
      #include<cstring>
      using  namespace  std;
      inline  int  mymax(int  x,int  y){return  x>y?x:y;}
      inline  int  mymin(int  x,int  y){return  x<y?x:y;}
      int  a[30];
      inline  bool  pd(){return  (a[7]==a[8]  &&  a[8]==a[9]  &&  a[9]==a[12]  &&  a[12]==a[13]  &&  a[13]==a[16]  &&  a[16]==a[17]  &&  a[17]==a[18]);}
      int  fuck[]={0,7,8,9,12,13,16,17,18};
      inline  int  check()
      {
          int  cnt=100;
          //左右第一个
          for(int  t=1;t<=3;t++)
          {
              int  tot=0;
              for(int  i=1;i<=8;i++)tot+=(a[fuck[i]]!=t);
              cnt=mymin(cnt,tot);
          }
          return  cnt;
      }
      inline  void  heng(int  l,int  r,int  type)
      {
          if(!type)//左拉 
          {
              int  x=a[l];
              for(int  i=l;i<r;i++)a[i]=a[i+1];
              a[r]=x;
          }
          else//右拉 
          {
              int  x=a[r];
              for(int  i=r;i>l;i--)a[i]=a[i-1];
              a[l]=x;
          }
      }
      int  li[2][8]={{0,1,3,7,12,16,21,23},{0,2,4,9,13,18,22,24}};
      inline  void  lie(int  *list,int  type)
      {
          if(!type)//上拉 
          {
              int  x=a[list[1]];
              for(int  i=1;i<7;i++)a[list[i]]=a[list[i+1]];
              a[list[7]]=x;
          }
          else//下拉 
          {
              int  x=a[list[7]];
              for(int  i=7;i>=2;i--)a[list[i]]=a[list[i-1]];
              a[list[1]]=x;
          }
      }
      int  limit;char  ans[30];int  top;
      int  fan[]={5,4,7,6,1,0,3,2};
      int  be1[]={0,0,1,1,0,0,1,1};
      int  be2[]={0,1,0,1,2,3,2,3};
      inline  void  do_op(int  x)
      {
          if(!x)lie(li[0],0);
          else  if(x==1)lie(li[1],0);
          else  if(x==2)heng(5,11,1);
          else  if(x==3)heng(14,20,1);
          else  if(x==4)lie(li[1],1);
          else  if(x==5)lie(li[0],1);
          else  if(x==6)heng(14,20,0);
          else  if(x==7)heng(5,11,0);
      }
      bool  dfs(int  dep,int  pre/*被ban掉的操作*/)
      {
          int  shit=check();
          if(dep+shit>limit)return  0;
          if(!shit)return  1;
          for(int  t=0;t<=7;t++)
          {
              if(pre!=100  &&  (t==fan[pre]  ||  (be1[t]==be1[pre]  &&  be2[t]<be2[pre])))continue;
              do_op(t);
              if(dfs(dep+1,t)==1)
              {
                  ans[dep]='A'+t;
                  return  1;
              }
              do_op(fan[t]);
          }
          return  0;
      }
      int  main()
      {
          while(1)
          {
              scanf("%d",&a[1]);
              if(!a[1])break;
              for(int  i=2;i<=24;i++)scanf("%d",&a[i]);
              if(pd()==1)
              {
                  printf("No moves needed\n%d\n",a[7]);
                  continue;
              }
              for(int  i=1;i<=100;i++)
              {
                  limit=i;
                  if(dfs(0,100)==1)
                  {
                      ans[i]='\0';
                      break;
                  }
              }
              printf("%s\n",ans);
              printf("%d\n",a[7]);
          }
          return  0;
      }
      • 1

      B30 IDA*算法 The Rotation Game[POJ2286]

      信息

      ID
      2980
      时间
      1000ms
      内存
      512MiB
      难度
      10
      标签
      递交数
      11
      已通过
      2
      上传者