题目描述

P2324 [SCOI2005]骑士精神_c

输入输出格式

输入格式:

第一行有一个正整数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

Solution:

  又是变量名打错,调了有一会儿~滑稽~!

  本题直接切入点是步数不超过$15$,很自然想到迭代加深搜索。

  那么直接限制深度搜,一个可行性剪枝就是统计一下当前没有被还原的棋子个数,若大于步数则直接剪掉。

  (瞎几把乱搞一通就好了,关键注意判重,不能回到上一个点,否则卡死循环。)

代码:

 

#include<bits/stdc++.h>
#define il inline
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
int T,ans,stx,sty,w[6][6],ed[6][6]={
    0,0,0,0,0,0,
    0,1,1,1,1,1,
    0,0,1,1,1,1,
    0,0,0,-1,1,1,
    0,0,0,0,0,1,
    0,0,0,0,0,0
};
char s;
int dx[8]={1,1,-1,-1,2,2,-2,-2},dy[8]={2,-2,2,-2,1,-1,1,-1};
bool f;
il void dfs(int x,int y,int t,int lstx,int lsty){
    if(!t)return;
    int tot=0;
    For(i,1,5) For(j,1,5)
        if(w[i][j]!=ed[i][j])tot++;
    if(!tot){f=1;return;}
    if((tot>>1)>t)return;
    For(i,0,7){
        int xx=dx[i]+x,yy=dy[i]+y;
        if(xx>0&&xx<6&&yy>0&&yy<6&&(xx!=lstx|yy!=lsty)){ 
            swap(w[xx][yy],w[x][y]),dfs(xx,yy,t-1,x,y),swap(w[xx][yy],w[x][y]);
        }
    }
}
il bool solve(){
    f=0;
    For(t,1,16){
        dfs(stx,sty,t,0,0);
        if(f){ans=t;return 1;}
    }
    return 0;
}
int main(){
    ios::sync_with_stdio(0);
    cin>>T;
    while(T--){
        For(i,1,5) For(j,1,5){
            cin>>s;
            if(s=='1')w[i][j]=1;
            if(s=='*')w[i][j]=-1,stx=i,sty=j;
            if(s=='0')w[i][j]=0;
        }
    if(solve())cout<<ans-1<<'\n';
        else cout<<-1<<'\n';
    }
    return 0;
}