1085: [SCOI2005]骑士精神

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 3371  Solved: 1990
[Submit][Status][Discuss]

Description

  在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑
士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空
位上。 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步
数完成任务。

Input

  第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑
士,*表示空位。两组数据之间没有空行。

Output

  对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。

Sample Input

2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100

Sample Output

7
-1
 
第一次写启发式搜索
直接dfs爆搜会TLE,于是就要用到神奇的A-star(简称A*)算法
 
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 const char mat[5][5]={'1','1','1','1','1',
 7                      '0','1','1','1','1',
 8                      '0','0','*','1','1',
 9                      '0','0','0','0','1',
10                      '0','0','0','0','0'};
11 
12 int T,x,y,k;
13 int mx[8]={-2,-1,1,2,2,1,-1,-2};
14 int my[8]={1,2,2,1,-1,-2,-2,-1};
15 char mp[10][10];
16 bool flag;
17 
18 void read()
19 {
20     flag=0;
21     for(int i=0;i<5;i++)
22         scanf("%s",mp[i]);
23     for(int i=0;i<5;i++)
24         for(int j=0;j<5;j++)
25             if(mp[i][j]=='*') x=i,y=j;
26 }
27 
28 bool check()
29 {
30     for(int i=0;i<5;i++)
31         for(int j=0;j<5;j++)
32             if(mp[i][j]!=mat[i][j]) return false;
33     return true;
34 }
35 
36 bool judge(int now)
37 {
38     int val=0;
39     for(int i=0;i<5;i++)
40         for(int j=0;j<5;j++)
41             if(mp[i][j]!=mat[i][j])
42             {
43                 val++;
44                 if(val+now>k) return false;
45             }
46     return true;
47 }
48 
49 void dfs(int now,int x,int y)
50 {
51     if(now>=k)
52     {
53         if(check()) flag=1;
54         return;
55     }
56     if(flag) return;
57     for(int i=0;i<8;i++)
58     {
59         int nx=x+mx[i],ny=y+my[i];
60         if(nx<0||nx>4||ny<0||ny>4) continue;
61         swap(mp[x][y],mp[nx][ny]);
62         if(judge(now)) dfs(now+1,nx,ny);
63         swap(mp[x][y],mp[nx][ny]);
64     }
65 }
66 
67 int main()
68 {
69     scanf("%d",&T);
70     while(T--)
71     {
72         read();
73         for(k=1;k<=15;k++)
74         {
75             dfs(0,x,y);
76             if(flag)
77             {
78                 printf("%d
",k);
79                 break;
80             }
81         }
82         if(!flag) printf("-1
");
83     }
84     return 0;
85 }
原文地址:https://www.cnblogs.com/InWILL/p/9457530.html