[SCOI2005]骑士精神

 

 

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1: 复制
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
输出样例#1: 复制
7
-1

说明

题解:

 看到题目,n=m=25----第一反应:爆搜

 毫无优化的爆搜写法-当前空白格往可以跳的个方向去跳,在跳的过程中判断--(因为马跳到空白格相当与空白格与马的位置互换-等于空白格跳到马的位置).

 考虑带一点点的优化-最优性剪枝:记录当前已经跳过的步数,如果已经超过记录的最优答案,返回-(显然这种方法对答案毫无贡献)

 再往深一点考虑-还学过什么优化-----迭代加深。

 发现还是卡不过去----于是就加上了A*-

 这里先介绍A*--对于当前的局面,计算一个最优方案可以到达最终结果的方式(可能达不到),如果当前的步数加上预计最好的步数还完不成的话,返回。

 对于每个题目,估价函数会不同,针对这个题目-最优的方案肯定是空白格每一次都可以使一匹马回到正确的位置,(当然可能不能实现-这里只是对未来的估价-并不等价与未来的真正结果)

 所以-我们记录当前的当前的状态与目标状态对比,如果一个不同就cnt++(这里的cnt就是对未来的最优估价)

 接下来!!!!!!!!!!!!! 上代码

 1 #include<bits/stdc++.h>
 2 #define R register
 3 
 4 using namespace std;
 5 
 6 inline long long read(){
 7    long long w=1,s=0;
 8    char ch=getchar();
 9    while(ch<'0'||ch>'9') {if (ch=='-') w=-1;ch=getchar();} 
10    while(ch>='0'&&ch<='9')  s=s*10+ch-'0',ch=getchar();
11    return s*w;
12 }
13 
14 int ans[6][6]={
15         {0,0,0,0,0,0},
16         {0,2,2,2,2,2},
17         {0,1,2,2,2,2},
18         {0,1,1,0,2,2},
19         {0,1,1,1,1,2},
20         {0,1,1,1,1,1}
21 };
22 
23 int num[10][10],dep,flag=0,n,m;
24 char ch[10][10];
25 int dx[9]={0,1,1,-1,-1,2,2,-2,-2};
26 int dy[9]={0,2,-2,2,-2,1,-1,1,-1};
27 
28 int evaluate(){
29     int tmp=0;
30     for(int i=1;i<=5;i++)
31     for(int j=1;j<=5;j++) tmp+=(num[i][j]==ans[i][j])?0:1;
32     return tmp;
33 }
34 
35 void dfs(int x,int y,int deep){
36     if (deep==dep){if (!evaluate()) flag=1;return ;}
37     for(int i=1;i<=8;i++){
38         int tox=x+dx[i],toy=y+dy[i];
39         if (tox>=1&&tox<=n&&toy>=1&&toy<=m){
40         swap(num[x][y],num[tox][toy]);
41         if (deep+evaluate()<=dep) dfs(tox,toy,deep+1);
42         swap(num[x][y],num[tox][toy]);
43         }
44     }
45 }
46 
47 int main(){
48 // freopen("a.in","r",stdin);
49     int T=read(),x,y;
50     n=5;m=5;
51     while(T--){
52     flag=0;
53     for(int i=1;i<=n;i++)
54     for(int j=1;j<=m;j++)
55     cin>>ch[i][j];
56     for(int i=1;i<=n;i++)
57     for(int j=1;j<=m;j++){
58         if (ch[i][j]!='*') num[i][j]=ch[i][j]-'0'+1;
59         else x=i,y=j,num[i][j]=0;
60     }
61     if (!evaluate()){ cout<<0<<endl; continue;}
62     for(dep=1;dep<=15;dep++){
63      dfs(x,y,0);
64      if (flag) {cout<<dep<<endl;break;}
65      }
66      if (!flag) cout<<"-1"<<endl;
67     }
68     return 0;
69 }

 

转载于:https://www.cnblogs.com/Yldar/p/9822678.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值