zoukankan      html  css  js  c++  java
  • BZOJ 1085 / LOJ 2151 [SCOI2005]骑士精神 (迭代加深搜索)

    题目大意:略

    upd in 2021.7.9

    每次都比较当前棋盘与目标棋盘会造成大小为25的常数,考虑统计出当前棋盘和目标棋盘不同的位置的数量k,那么当前棋盘变成目标棋盘最少的移动次数是k-1,只有最后一次会让差异一下子减少二,其他的情况本质上最多只能减少1

    每次选择一个最大深度ma,那么如果当前走了dep步,显然必须保证dep+k-1<=ma,否则当前棋盘就是永远无法在规定步数ma内到达目标棋盘

     1 #include <queue>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define NN 65538
     6 #define MM 100
     7 #define ll long long 
     8 #define uint unsigned int
     9 #define ull unsigned long long 
    10 #define inf 0x3f3f3f3f
    11 #define idx(X,Y) ((X)*5+(Y))
    12 using namespace std;
    13 
    14 int T;
    15 const int Ed=549855;
    16 const int maxn=65535;
    17 int mp[7][7],bin[30],cnt[NN];
    18 int xx[]={-2,-1,1,2,2,1,-1,-2};
    19 int yy[]={1,2,2,1,-1,-2,-2,-1};
    20 int check(int x,int y)
    21 {if(x<0||y<0||x>4||y>4)return 0;return 1;}
    22 int dfs(int dep,int s,int p,int ma,int fa,int fp)
    23 {
    24     if(s==Ed&&p==12) return 1;
    25     if(dep>=ma) return 0;
    26     int x=p/5,y=p%5;
    27     int tx,ty,t,tp,sum,h,ans;
    28     sum=Ed^s;
    29     h=cnt[sum&maxn]+cnt[sum>>16];
    30     if((p!=12)&&(!(sum&(1<<p)))&&(!(Ed&(1<<p)))) h++;
    31     if((p!=12)&&(!(sum&(1<<12)))&&(!(s&(1<<12)))) h++;
    32     if(dep+h-1>ma) return 0;
    33     for(int k=0;k<8;k++)
    34     {
    35         tx=x+xx[k],ty=y+yy[k];
    36         if(!check(tx,ty)) continue;
    37         if(s&(bin[idx(tx,ty)]))
    38             t=(s^bin[idx(tx,ty)])|bin[idx(x,y)];
    39         else t=s;
    40         tp=idx(tx,ty);
    41         if(t==fa&&tp==fp) continue;
    42         ans=dfs(dep+1,t,tp,ma,s,p);
    43         if(ans) return 1;
    44     }return 0;
    45 }
    46 
    47 int main()
    48 {
    49     //freopen("t2.in","r",stdin);
    50     scanf("%d",&T);
    51     bin[0]=1;
    52     for(int i=1;i<=25;i++)
    53         bin[i]=bin[i-1]<<1;
    54     for(int i=0;i<65536;i++)
    55         for(int j=0;j<16;j++)
    56             if(i&(1<<j)) cnt[i]++;
    57     while(T--)
    58     {
    59         char str[10];int s=0,p;
    60         for(int i=0;i<5;i++)
    61         {
    62             scanf("%s",str);
    63             for(int j=0;j<5;j++){
    64                 if(str[j]=='*'){
    65                     p=idx(i,j);
    66                 }else if(str[j]=='1'){
    67                     s|=(bin[idx(i,j)]);
    68                 }
    69             }
    70         }
    71         int fl=0;
    72         for(int k=0;k<=15;k++){
    73             int ans=dfs(0,s,p,k,-1,0);
    74             if(ans){
    75                 printf("%d
    ",k);
    76                 fl=1;break;}
    77         }
    78         if(!fl) printf("-1
    ");
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    《java并发编程实战》读书笔记9--并发程序的测试
    《java并发编程实战》读书笔记8--死锁,性能与可伸缩性,锁粒度锁分解锁分段
    笔试算法题记录1
    _stdcall调用
    通信设备硬件工程师应该具备的基本能力和知识
    PCB产业链、材料、工艺流程详解(1)
    PCB中加入任意LOGO图文说明 精心制作
    开关电源基础知识(一)
    六个框架,一百多条检查项目,保证PCB设计不再出错
    开关电源PCB排版,基本要点分析
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10009347.html
Copyright © 2011-2022 走看看