题目链接

最小步数这类,适合用迭代加深搜索。

用空格走代替骑士。

搜索时记录上一步防止来回走。

不需要每次判断是否都在位置,可以计算出不在对应位置的骑士有多少个。而且每次复原一个骑士至少需要一步。

空格是不计算未复原骑士数的。

//820kb	84ms
#include <cstdio>
#include <cstring>
#include <algorithm>
#define n (5)
typedef long long LL;
const int way_x[9]={1,1,2,2,-2,-2,-1,-1},way_y[9]={2,-2,1,-1,1,-1,2,-2};
const int End[6][6]=
{{0},
{0,1,1,1,1,1},
{0,0,1,1,1,1},
{0,0,0,2,1,1},
{0,0,0,0,0,1},
{0,0,0,0,0,0},
}; int mp[7][7];
char s[10]; bool DFS(int x,int y,int left,int sum,int las)
{
if(sum>left) return 0;
if(!sum) return 1;
for(int xn,yn,res,i=0; i<8; ++i)
if(i!=7-las&&(xn=x+way_x[i])>0&&(yn=y+way_y[i]) >0&&xn<=n&&yn<=n)
{
res=sum;
if(mp[xn][yn]==End[xn][yn]) ++res; std::swap(mp[x][y],mp[xn][yn]); if(mp[x][y]==End[x][y]) --res; bool f=DFS(xn,yn,left-1,res,i);
if(f) return 1;
std::swap(mp[x][y],mp[xn][yn]);
}
return 0;
} int main()
{
int T,sx,sy,init; scanf("%d",&T);
while(T--)
{
for(int i=1; i<=n; ++i)
{
scanf("%s",s+1);
for(int j=1; j<=n; ++j)
if(s[j]!='*') mp[i][j]=s[j]-'0';
else mp[i][j]=2,sx=i,sy=j;
}
init=0;
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
if(mp[i][j]!=End[i][j]) ++init;//init:至少需要 多少步。
if(sx!=3||sy!=3) --init;//空格不计算未复原骑士数。
// printf("init:%d\n",init);
for(int dep=init; ; ++dep)
if(dep==16) {puts("-1"); break;}
else if(DFS(sx,sy,dep,init,8)) {printf("%d\n",dep); break;}
}
return 0;
}

附上sb哈希的代码吧。。真是学傻了。

#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define n (5)
typedef long long LL;
const int way_x[9]={1,1,2,2,-1,-1,-2,-2},way_y[9]={2,-2,1,-1,2,-2,1,-1};
const int End[6][6]=
{{0},
{0,1,1,1,1,1},
{0,0,1,1,1,1},
{0,0,0,2,1,1},
{0,0,0,0,0,1},
{0,0,0,0,0,0},
}; int mp[7][7];
short Ans;
char s[10];
std::map<LL,short> vis;
std::set<LL> st; bool Victory()
{
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
if(mp[i][j]!=End[i][j]) return 0;
return 1;
}
LL Encode()
{
LL res=0;
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j) res=res*3+mp[i][j];
// if(Victory()){
// printf("%I64d:\n",res);
// for(int i=1; i<=n; ++i,putchar('\n'))
// for(int j=1; j<=n; ++j) printf("%d ",mp[i][j]);
// }
return res;
}
short DFS(int x,int y,short step,LL s)
{
if(step>15) return 16;
if(Ans<=step) return 17;
if(x==3&&y==3&&Victory()) {Ans=std::min(Ans,step); return step;} short res=17; LL ss;
for(int xn,yn,i=0; i<8; ++i)
if((xn=x+way_x[i])>0&&(yn=y+way_y[i])>0&&xn<=n&&yn<=n)
{
std::swap(mp[x][y],mp[xn][yn]);
ss=Encode();
if(!st.count(ss))
st.insert(ss),res=std::min(res,DFS(xn,yn,step+1,ss)),st.erase(ss);
std::swap(mp[x][y],mp[xn][yn]);
}
return res;
} int main()
{
int T,sx,sy; scanf("%d",&T);
while(T--)
{
Ans=16, st.clear(), vis.clear();
for(int i=1; i<=n; ++i)
{
scanf("%s",s+1);
for(int j=1; j<=n; ++j)
if(s[j]!='*') mp[i][j]=s[j]-'0';
else mp[i][j]=2,sx=i,sy=j;
}
LL s=Encode();
st.insert(s);
DFS(sx,sy,0,s);
printf("%d\n",Ans<=15?Ans:-1);
}
return 0;
}

BZOJ.1085.[SCOI2005]骑士精神(迭代加深搜索)的更多相关文章

  1. BZOJ1085: [SCOI2005]骑士精神 [迭代加深搜索 IDA*]

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1800  Solved: 984[Submit][Statu ...

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

    Bzoj 1085: [SCOI2005]骑士精神 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 dfs + 剪枝. 剪枝方法: ...

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

    一开始写了个 BFS 然后就 T 了... 这道题是迭代加深搜索 + A* -------------------------------------------------------------- ...

  4. BZOJ 1085 [SCOI2005]骑士精神 【A*启发式搜索】

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2838  Solved: 1663 [Submit][St ...

  5. BZOJ 1085 骑士精神 迭代加深搜索+A*

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1085 题目大意: 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个 ...

  6. bzoj 1085 [SCOI2005]骑士精神——IDA*

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 迭代加深搜索. 估价函数是为了预计步数来剪枝,所以要优于实际步数. 没错,不是为了确定 ...

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

    题目链接 : BZOJ 1085 题目分析 : 本题中可能的状态会有 (2^24) * 25 种状态,需要使用优秀的搜索方式和一些优化技巧. 我使用的是 IDA* 搜索,从小到大枚举步数,每次 DFS ...

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

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1085 分析: 首先第一感觉是宽搜,但是空间需要8^15*5*5,明显不够,又鉴于最大深 ...

  9. bzoj 1085: [SCOI2005]骑士精神

    Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士,且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵 ...

随机推荐

  1. windows服务写完之后怎么让它跑起来

    当然你可以在命令框里面自己去手动的敲代码,也可以写一个.bat文件一劳永逸......这里我就介绍写.bat文件的方法 就是上图所示的三个东东啦,有了这三个东东,把他们拖到你windows服务的deb ...

  2. Linux问题集锦

    一些会遇到的问题,我会不断更新问题集锦~  1.vi / vim保存文件时遇到的问题:E212: Can't open file for writing 在vi / vim下输入w或wq!保存编辑的文 ...

  3. np.random.rand均匀分布随机数和np.random.randn正态分布随机数函数使用方法

    np.random.rand用法 觉得有用的话,欢迎一起讨论相互学习~Follow Me 生成特定形状下[0,1)下的均匀分布随机数 np.random.rand(a1,a2,a3...)生成形状为( ...

  4. Swift学习笔记1

    1.Swift 的String类型是值类型. 如果您创建了一个新的字符串,那么当其进行常量.变量赋值操作,或在函数/方法中传递时,会进行值拷贝. 任何情况下,都会对已有字符串值创建新副本,并对该新副本 ...

  5. 小议 开源中国 I LOVE YOU js代码

    今天在开源中国看到一篇神作<I LOVE YOU js代码>是17号的文章了,也许你已经看过了. 文章非常有意思,由 5 个 "爱心" 组成的一段js代码,能正常执行, ...

  6. mysql先排序在分组

    – 表的结构 `test`– CREATE TABLE IF NOT EXISTS `test` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varcha ...

  7. linux - 流量切分线路

    流量切分线路方式 # 程序判断进入IP线路,设置服务器路由规则控制返回 vi /etc/iproute2/rt_tables #添加一条策略 bgp2 #注意策略的序号顺序 ip route add ...

  8. 在一台win10上启动多个mysql

    1.因为项目需要用一个已经有数据的mysql,而我之前已经安装了一个mysql(之前的mysql上面也是有东西,不想删除)  想办法.... mysqld.exe --defaults-file=D: ...

  9. Android 常用动画之RotateAnimation

    前两天接到任务做一个UI,有用到动画,于是抽空看了下Android动画相关知识. Android Animation共有四大类型,分别是 Alpha      透明度动画 Scale      大小伸 ...

  10. 字符串前面加u、r、b的含义

    u/U:表示unicode字符串 不是仅仅是针对中文, 可以针对任何的字符串,代表是对字符串进行unicode编码. 一般英文字符在使用各种编码下, 基本都可以正常解析, 所以一般不带u:但是中文, ...