BZOJ 1085 [SCOI2005]骑士精神

据说是A_star的裸题,感觉就是爆搜剪枝。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
int ans,T,x,y;
char a[6][6],b[6][6]={{"11111"}, {"01111"}, {"00*11"}, {"00001"}, {"00000"}};
int xx[10]={-1,-1,1,1,-2,-2,2,2},yy[10]={-2,2,-2,2,-1,1,1,-1};
int ok(int i,int j) {return i>=0&&i<5&&j>=0&&j<5;}
int check(char a[][6],char b[][6]) {
    int res=0;
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
            if(a[i][j]!=b[i][j]) res++;
    return res;
}
int same(char a[][6],char b[][6]) {
    int res=0;
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
            if(a[i][j]!=b[i][j]) return 0;
    return 1;
}
void dfs(int dep) {
    if(same(a,b)) {
        ans=min(ans,dep);
        return;
    }
    if(dep>min(ans,15)) return;
    for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(a[i][j]==‘*‘) x=i,y=j;
    for(int i=0;i<8;i++) {
        x+=xx[i]; y+=yy[i];
        if(ok(x,y)){
            swap(a[x][y],a[x-xx[i]][y-yy[i]]);
            if(check(a,b)+dep<=ans) dfs(dep+1);
            swap(a[x][y],a[x-xx[i]][y-yy[i]]);
        }
        x-=xx[i]; y-=yy[i];
    }
}
int main() {
    scanf("%d",&T);
    while(T--) {
        for(int i=0;i<5;i++)
        scanf("%s",a[i]);
        ans=16;
        dfs(0);
        if(ans==16) printf("-1\n");
        else printf("%d\n",ans);
    }
    return 0;
}

时间: 2024-10-08 09:29:52

BZOJ 1085 [SCOI2005]骑士精神的相关文章

Bzoj 1085: [SCOI2005]骑士精神 (dfs)

Bzoj 1085: [SCOI2005]骑士精神 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 dfs + 剪枝. 剪枝方法: 1.每次交换只能改变一个位置.若发现之间相差的步数加上以前走的步数大于15的话,直接舍弃这一状态. 2.初始时,\(ans\)设为\(16\) 有了上面两个剪枝就A了. 照这节奏,SCOI2005就刷完了??? #include <iostream> #include <cstdio>

BZOJ 1085: [SCOI2005]骑士精神( IDDFS + A* )

一开始写了个 BFS 然后就 T 了... 这道题是迭代加深搜索 + A* ------------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define rep( i , n ) for( int i = 0 ; i

[BZOJ 1085] [SCOI2005] 骑士精神 [ IDA* 搜索 ]

题目链接 : BZOJ 1085 题目分析 : 本题中可能的状态会有 (2^24) * 25 种状态,需要使用优秀的搜索方式和一些优化技巧. 我使用的是 IDA* 搜索,从小到大枚举步数,每次 DFS 验证在当前枚举的步数之内能否到达目标状态. 如果不能到达,就枚举下一个步数,重新搜索,即使某些状态在之前的 DFS 中已经搜索过,我们仍然搜索. 并且在一次 DFS 中,我们不需要判定重复的状态. 在 IDA* 中,重要的剪枝优化是 估价函数 ,将一些不可能存在可行解的枝条剪掉. 如果估价函数写得

[BZOJ 1085][SCOI2005]骑士精神(IDA*)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1085 分析: 首先第一感觉是宽搜,但是空间需要8^15*5*5,明显不够,又鉴于最大深度为15,所以可以用迭代加深做. 但是普通的迭代加深还是会TLE.于是考虑加上估价函数 设当前层数的上界为Kmax,当前搜索的层数为K,我们知道一次移动顶多改变目前矩阵和目标矩阵的一个差别,于是可以求出当前与目标矩阵不同的位置的个数s,如果k+s>Kmax那么就可以直接不做了.

bzoj 1085: [SCOI2005]骑士精神 IDA*

题目链接 给一个图, 目标位置是确定的, 问你能否在15步之内达到目标位置. 因为只有15步, 所以直接ida* #include<bits/stdc++.h> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define mem(a) memset(a, 0, sizeof(

【BZOJ】1085: [SCOI2005]骑士精神

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1085 $${if (cs+val-1>ans) return ;}$$ 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #inc

bzoj1085 [SCOI2005]骑士精神

1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2490  Solved: 1422[Submit][Status][Discuss] Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上. 给定一个初始的棋盘,怎样才能经过移动

【bzoj1085】[SCOI2005]骑士精神

1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1757  Solved: 961[Submit][Status][Discuss] Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上. 给定一个初始的棋盘,怎样才能经过移动变

洛谷 P2324 [SCOI2005]骑士精神

P2324 [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 输出样例