Uvaoj10422-Knight in FEN(细节+重点)

Uvaoj 10422

      There are black and white knights on a 5 by 5 chessboard. There are twelve of each color, and there
is one square that is empty. At any time, a knight can move into an empty square as long as it moves
like a knight in normal chess (what else did you expect?).
Given an initial position of the board, the question is: what is the minimum number of moves in
which we can reach the final position which is:



                                                 


Input
First line of the input file contains an integer N (N < 14) that indicates how many sets of inputs are
there. The description of each set is given below:
Each set consists of five lines; each line represents one row of a chessboard. The positions occupied
by white knights are marked by ‘0’ and the positions occupied by black knights are marked by ‘1. The
space corresponds to the empty square on board.
There is no blank line between the two sets of input.
Note: The first set of the sample input below corresponds to this configuration:


                                                                         



Output
For each set your task is to find the minimum number of moves leading from the starting input config-
uration to the final one. If that number is bigger than 10, then output one line stating
Unsolvable in less than 11 move(s).
otherwise output one line stating
Solvable in n move(s).
where n ≤ 10.
The output for each set is produced in a single line as shown in the sample output.
Sample Input
2
01011
110  1
01110
01010
00100
10110
01  11
10111
01001
00000
Sample Output
Unsolvable in less than 11 move(s).
Solvable in 7 move(s).


   该题我是被拌的不轻,很费解,一直以为是自己控制条件不对,导致无限加入了重复状态,没法结束循环。后来我就用C++做了一遍,这回就用set容器做,set.count(变量)可以判重,若等于0 ,说明就没有加过这种情况。(还是用同样的控制条件)。

   然而奇迹就这样发生了!超过8步就可以运行出结果了,说明一个非常重要的问题,就是算法的效率!

   如果你用的是这样的算法:

  void try_to_insert( int n)

 {

     int i;

     for(i=0;i<n;i++)

     {

         if(memset(state[i].s , now ,sizeof(nowcmp))==0)return 0;   //当前要加入的一组数(now)和已存入队列中                                                                                                              //的所数进行比较,看有没有重复,

     }                                                                                                                                                                                        

    return 1;

}


那么你跟我一样 ,在输出到8以后就非常慢了!最后就会  时间超时了。

---------------------------------------------------------------------------------------------------------------------------------------------------------

所以本题的关键是  判重的效率!

STL 中的  set是常见用法 

重点是理解 算法的效率。

   有一个细节,别忘了,你们有没有遇到就0步的情况 ,但是输出时Unsolvable ...11 movs. 看看是不是因为步数为0 就返回该步数,就导致在主函数中 的if判断中 就无效了(由于是0而无法和>11步的区分开)。如果你们直接在BFS过程中就输出结果就不需要考虑了。

   细节二,在大于9步的时候其实就没必要循环加元素了,你也可以在大于11的时候直接结束BFS。

 

觉得自己的代码有点乱,重点的都说完了,还是自己写比较好。

#include<cstdio>
#include<iostream>
#include<set>
#include<queue>
#include<cstring>
using namespace std;
struct node
{
char s[26];
int step;
} ;
struct cmp
{
bool operator()(node a, node b) const
{
if(memcmp(a.s ,b.s ,25)<0)return 1;
else return 0;
}
};
set<node,cmp>state;
queue<node>que;
char squ[26];
char final[26]={"111110111100 110000100000"};
int d[8][2] ={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2}};
int res;
node copyy;
int check( )
{
if(state.count(copyy))return 0;
copyy.step ++;
state.insert(copyy);
return 1;
}
int bfs()
{
int m1, i , m2;
    int x,y;
char t;


    memcpy(copyy.s,squ,25);
copyy.step = 0;
state.insert (copyy);
que.push(copyy);

while(!que.empty())
{
 
                copyy = que.front ();
que.pop();
  
 if(memcmp(copyy.s,final,25)==0)
 {  
                  res =  copyy.step + 1 ;
 return res;
 }
      
 for(m1=0;m1<25;m1++)
  if(copyy.s [m1]==' ')
 break;
 if(copyy.step <= 9)
 for(i=0;i<8;i++)
 {  
 x = m1/5 + d[i][0];
 y = m1%5 + d[i][1];
 
 
 if(x<5 && y<5 && x>=0 && y>=0 )
 {
 m2 = x*5 + y;  
 t = copyy.s [m1];
     copyy.s [m1] = copyy.s [m2];
     copyy.s [m2] = t;
                     if(check())
 {
 que.push (copyy);
 copyy.step --;
 } 
 t = copyy.s[m1];
     copyy.s [m1] = copyy.s [m2];
     copyy.s [m2] = t;
 }  
 }
         
}
  return 0;



void clear()
{
while(!que.empty())que.pop();
state.clear();
}
int main()
{
int n , i;
char c;
scanf("%c",&c);


getchar();
while(n--)
{

clear();
i=0;

        while(i<25)
{
c = getchar();
if(c=='\n')
continue;
else squ[i++] = c;
}
                squ[i]='\0';
res = 1000;
if(bfs())
printf("Solvable in %d move(s).\n",res-1);
else
printf("Unsolvable in less than 11 move(s).\n");


}




return 0;
}





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值