【BZOJ】【1085】【SCOI2005】骑士精神

IDA*算法

  Orz HZWER

  A*+迭代加深搜索=IDA*

  这题的估价相当于一个可行性剪枝,即如果当前走的步数s+未归位的点数>搜索深度k,则剪枝

  

 1 /**************************************************************
 2     Problem: 1085
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:1388 ms
 7     Memory:1272 kb
 8 ****************************************************************/
 9
10 //BZOJ 1085
11 #include<cstdio>
12 #include<cstdlib>
13 #include<cstring>
14 #include<iostream>
15 #include<algorithm>
16 #define rep(i,n) for(int i=0;i<n;++i)
17 #define F(i,j,n) for(int i=j;i<=n;++i)
18 #define D(i,j,n) for(int i=j;i>=n;--i)
19 using namespace std;
20
21 int getint(){
22     int v=0,sign=1; char ch=getchar();
23     while(ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) sign=-1; ch=getchar();}
24     while(ch>=‘0‘&&ch<=‘9‘) {v=v*10+ch-‘0‘; ch=getchar();}
25     return v*=sign;
26 }
27 /*******************tamplate********************/
28 int k;
29 const int ans[5][5]={{1,1,1,1,1},
30                      {0,1,1,1,1},
31                      {0,0,2,1,1},
32                      {0,0,0,0,1},
33                      {0,0,0,0,0}};
34 const int fx[8]={1,1,-1,-1,2,2,-2,-2},
35           fy[8]={2,-2,2,-2,1,-1,1,-1};
36
37 bool flag=0;
38 bool judge(int a[5][5]){
39     rep(i,5)
40         rep(j,5)
41             if (ans[i][j]!=a[i][j]) return 0;
42     return 1;
43 }
44 bool eva(int a[5][5],int s){
45     int v=0;
46     rep(i,5)
47         rep(j,5)
48             if (a[i][j]!=ans[i][j]){
49                 v++;
50                 if(v+s>k) return 0;
51             }
52     return 1;
53 }
54 //v¼´Îª¹À¼Ûº¯Êý£¨Èç¹û¸úans²î¾àÌ«´ó£¬²»¿ÉÄÜÔÚk²½Ö®ÄÚ³ö½â£¬ÔòÉáÆú
55 void search(int s,int a[5][5],int x,int y){
56     if (s==k) {if (judge(a)) flag=1; return;}
57     if (flag==1) return;
58     rep(i,8){
59         int tx=x+fx[i],ty=y+fy[i];
60         if (tx<0||tx>4||ty<0||ty>4) continue;
61         swap(a[x][y],a[tx][ty]);
62         if (eva(a,s)) search(s+1,a,tx,ty);
63         swap(a[x][y],a[tx][ty]);
64     }
65 }
66 int main(){
67     int T=getint();
68     char ch[10];
69     while(T--){
70         int a[5][5],x,y;
71         memset(a,0,sizeof a);
72         rep(i,5){
73             scanf("%s",ch);
74             rep(j,5)
75                 if (ch[j]==‘*‘){ a[i][j]=2;x=i;y=j; }
76                 else a[i][j]=ch[j]-‘0‘;
77         }
78         flag=0;
79         for(k=1;k<=15;++k){
80             search(0,a,x,y); if (flag){ printf("%d\n",k);break;}
81         }
82         if (!flag) printf("-1\n");
83     }
84     return 0;
85 }

时间: 2024-10-22 08:19:14

【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]骑士精神

据说是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

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