[bzoj1085][SCOI2005]骑士精神【暴力】

【题目链接】
  http://www.lydsy.com/JudgeOnline/problem.php?id=1085
【题解】
  dfs+剪枝即可。
  剪枝的方法是,若当前状态与目标状态有k个不同。那么至少还要使用k1步。若+k1 ans则直接退出。
  

/* --------------
    user Vanisher
    problem bzoj-1085
----------------*/
# include <bits/stdc++.h>
# define    ll      long long
# define    inf     0x3f3f3f3f
using namespace std;
int read(){
    int tmp=0, fh=1; char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    return tmp*fh;
}
char tt[6][6];
int ans,n;
int mp[5][5];
const int dx[8]={1,2,2,1,-1,-2,-2,-1}, dy[8]={-2,-1,1,2,2,1,-1,-2},
o[5][5]={   1,1,1,1,1,
            0,1,1,1,1,
            0,0,2,1,1,
            0,0,0,0,1,
            0,0,0,0,0};
int check(){
    int num=0;
    for (int i=0; i<5; i++)
        for (int j=0; j<5; j++)
            num+=(mp[i][j]!=o[i][j]);
    return num;
}
void solve(int k, int x, int y){
    int s=check();
    if (s==0){
        ans=k;
        return;
    }
    if (k+s-1>=ans) return;
    for (int t=0; t<8; t++){
        int tx=x+dx[t], ty=y+dy[t];
        if (tx<0||ty<0||tx>=5||ty>=5) continue;
        swap(mp[x][y],mp[tx][ty]);
        solve(k+1,tx,ty);
        swap(mp[x][y],mp[tx][ty]);
    }
}
int main(){
    n=read();
    for (int opt=1; opt<=n; opt++){
        int x,y;
        for (int i=0; i<5; i++){
            scanf("\n%s",&tt[i]);
            for (int j=0; j<5; j++){
                if (tt[i][j]=='*') mp[i][j]=2,x=i,y=j;
                    else mp[i][j]=tt[i][j]-'0';
            }
        }
        ans=16;
        solve(0,x,y);
        if (ans==16)
            printf("%d\n",-1);
            else printf("%d\n",ans);
    }
    return 0;
}
posted @ 2018-03-07 18:52  Vanisher  阅读(23)  评论(0编辑  收藏