[BZOJ1085【骑士精神】]

1 篇文章 0 订阅
1 篇文章 0 订阅

BZOJ1085【骑士精神】

这道题很明显是一道BFS或者是A*+迭代加深。
BFS也可可以套个A*估值,再用优先队列去维护。
不多说,直接现代码:
BFS+A*

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<string>
using namespace std;
string goal="111110111100*110000100000";
struct ss{
    int x,y,dep,gu;
    string A;
    ss(){A="";}
    void g(){
        gu=0;
        for(int i=0;i<25;i++)if(goal[i]!=A[i])gu++;
    }
    bool operator<(const ss &a)const{
        return dep+gu>a.dep+a.gu;
    }
};
int ra[]={2,-2,1,-1,2,-2,1,-1};
int rb[]={1,-1,2,-2,-1,1,-2,2};
int solve(ss a){// BFS
    map<string,bool>mp;
    priority_queue<ss>Q;
    a.g();
    Q.push(a);
    while(!Q.empty()){
        ss no=Q.top();Q.pop();
        for(int i=0;i<8;i++){
            ss nxt;
            nxt.x=no.x+ra[i];
            nxt.y=no.y+rb[i];
            if(nxt.x>=0&&nxt.y>=0&&nxt.x<5&&nxt.y<5){
                nxt.A=no.A;
                swap(nxt.A[nxt.x*5+nxt.y],nxt.A[no.x*5+no.y]);
                if(mp[nxt.A])continue;
                nxt.dep=no.dep+1;
                if(nxt.A==goal)return nxt.dep;
                mp[nxt.A]=1;
                nxt.g();
                if(nxt.dep<15&&no.dep+nxt.gu<=15)Q.push(nxt);
            }
        }
    }
    return -1;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        ss a;a.dep=0;
        for(int i=0;i<5;i++){
            char s[8];scanf("%s",s);
            for(int j=0;j<5;j++){
                if(s[j]=='*'){
                    a.x=i;a.y=j;
                }a.A+=s[j];
            }
        }
        if(a.A==goal)puts("0");
        else printf("%d\n",solve(a));
    }
    return 0;
}

A*+迭代加深

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<string>
using namespace std;
string goal="111110111100*110000100000";
int ra[]={2,-2,1,-1,2,-2,1,-1};
int rb[]={1,-1,2,-2,-1,1,-2,2};
string a;
int g(){
    int gu=0;
    for(int i=0;i<25;i++)if(goal[i]!=a[i])gu++;
    return gu;
}
bool flag=false;
void solve(int x,int y,int left){
    if(a==goal){flag=true;return;} 
    if(g()>left-1)return;
    if(left)
        for(int i=0;i<8&&!flag;i++){
            int xx=x+ra[i];
            int yy=y+rb[i];
            if(xx>=0&&yy>=0&&xx<5&&yy<5){ 
                swap(a[xx*5+yy],a[x*5+y]);
                solve(xx,yy,left-1);
                swap(a[xx*5+yy],a[x*5+y]);
            }
        }
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        a="";
        int xx,yy;
        for(int i=0;i<5;i++){
            char s[8];scanf("%s",s);
            for(int j=0;j<5;j++){
                if(s[j]=='*'){
                    xx=i;yy=j;
                }a+=s[j];
            }
        }
        int ans=16;
        flag=false;
        for(int i=0;i<16;i++){//迭代+A* 
            solve(xx,yy,i);
            if(flag){ans=i;break;}
        }
        printf("%d\n",ans==16?-1:ans);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值