BZOJ 1085 / LOJ 2151 [SCOI2005]骑士精神 (剪枝/A*迭代搜索)

题目大意:略

直接爆搜会T,我们优化一下,统计出当前棋盘和目标棋盘不同的位置的数量k,那么当前棋盘变成目标棋盘最少的移动次数是k-1

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

其实这个不算很A*吧...应该算剪枝

移动方向的数量打错了WA了好久...另外LOJ上有这道题的数据

 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\n",k);
76                 fl=1;break;}
77         }
78         if(!fl) printf("-1\n");
79     }
80     return 0;
81 }

 

posted @ 2018-11-23 19:15  guapisolo  阅读(88)  评论(0编辑  收藏