本章聚集了一些做了的迭代启发式搜索的题目

为什么只打了迭代启发式搜索?

因为它很好打,有些类似迭代的时候加的最优化剪枝

[因为这个最优化剪枝其实就是你算的估价函数了...]

BZOJ 1085 骑士精神

比较经典的一题,特别是题目中还说了在15步内走完...看上去就是迭代的样子

估价函数->指棋盘上不符合规定的骑士数目...每次移动最多让一名骑士回到自己的位置,由此来剪枝

 #include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; int maxd,sx,sy;
char ch[][];
int x[]={,,-,-,,,-,-};
int y[]={,-,,-,,-,,-};
int ans[][]={{,,,,},{,,,,},{,,,,},{,,,,},{,,,,}}; struct Node{
int a[][];
int illegal(){
int cnt=;
for(int i=;i<;i++)
for(int j=;j<;j++)
if(a[i][j]!=ans[i][j]) cnt++;
return cnt;
}
}; inline bool judge(int a[][]){
for(int i=;i<;i++)
for(int j=;j<;j++)
if(a[i][j]!=ans[i][j]) return false;
return true;
} inline bool inmap(int x,int y){
if(x>= || x< || y>= || y<) return false;
return true;
} bool dfs(int level,Node s,int bx,int by){
if(!level){
if(judge(s.a)) return true;
return false;
}
int newx,newy;
for(int i=;i<;i++){
newx=bx+x[i],newy=by+y[i];
if(inmap(newx,newy)){
swap(s.a[bx][by],s.a[newx][newy]);
if(s.illegal()<=level)
if(dfs(level-,s,newx,newy)) return true;
swap(s.a[bx][by],s.a[newx][newy]);
}
}
return false;
} int main(){
#ifndef ONLINE_JUDGE
freopen("1085.in","r",stdin);
freopen("1085.out","w",stdout);
#endif
int kase;
Node s;
scanf("%d",&kase);
while(kase--){
for(int i=;i<;i++){
scanf("%s",ch[i]);
for(int j=;j<;j++)
if(ch[i][j]=='*') s.a[i][j]=,sx=i,sy=j;
else if(ch[i][j]=='') s.a[i][j]=;
else s.a[i][j]=;
}
if(!s.illegal()) {puts("");continue;}
for(maxd=;maxd<=;maxd++)
if(dfs(maxd,s,sx,sy)) break;
if(maxd<=)
printf("%d\n",maxd);
else
puts("-1");
}
return ;
}

codevs1288 埃及分数

强行把从某个状态之后的最小值看做估价函数也是可以的...紫书例题

不过有一些坑点,看codevs题解的第一篇吧(...我写的)。

 #include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; typedef long long ll; const int maxn=;
const int INF=0x7f7f7f7f; int a,b,d;
ll res[maxn],rec[maxn]; ll gcd(ll a,ll b){
ll t;
while(b)
t=b,b=a%b,a=t;
return a;
} inline bool better(ll a[]){
if(a[]>=res[]) return false;
else return true;
for(int i=;i<=d;i++)
if(a[i]<res[i]) return true;
else if(a[i]>res[i]) return false;
return false;
} bool dfs(int level,ll last,ll aa,ll bb){
if(level==){
if(bb%aa) return false;
rec[]=bb/aa;
if(better(rec))
for(int i=;i<=d;i++) res[i]=rec[i];
return true;
}
bool ok=false;
last=max(last+,(bb/aa)+!(bb%aa==));
for(int i=last;;i++){
if(aa*i>=bb*level) break;
ll b1=bb*i,a1=aa*i-bb,Gcd;
Gcd=gcd(a1,b1);
a1/=Gcd,b1/=Gcd;rec[level]=i;
if(dfs(level-,i,a1,b1)) ok=true;
}
return ok;
} int main(){
scanf("%d%d",&a,&b);
memset(res,0x7f,sizeof(res));
for(d=;!dfs(d,,a,b);d++);
for(int i=d;i>=;i--)
printf("%lld ",res[i]); return ;
}

codevs2495 水叮当的舞步

这题估价函数居然就是一个颜色?...我其实有想过什么连通块个数的估价然而没有什么用...

其实这题关键还是在于给左上角染色的过程,每次给变色的地方染1,变色的周围染2,然后每次的颜色只要扩展2中相同的就好...比每次dfs快上很多的样子...

 #include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; int maxd,n;
int mp[][],mark[][];
int xx[]={,-,,};
int yy[]={,,-,};
bool used[];
bool ans; int get(){
int cnt=;
memset(used,,sizeof(used));
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(!used[mp[i][j]] && mark[i][j]!=)
used[mp[i][j]]=,cnt++;
return cnt;
} void dfs(int a,int b,int x){
mark[a][b]=;
for(int i=;i<;i++){
int nowx=a+xx[i],nowy=b+yy[i];
if(nowx<||nowy<||nowx>n||nowy>n||mark[nowx][nowy]==) continue;
mark[nowx][nowy]=;
if(mp[nowx][nowy]==x)dfs(nowx,nowy,x);
}
} int fill(int x){
int cnt=;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(mark[i][j]==&&mp[i][j]==x)
cnt++,dfs(i,j,x);
return cnt;
} bool search(int level){
int v=get();
if(!v) return true;
if(v>level) return false;
int temp[][];
for(int i=;i<=;i++){
memcpy(temp,mark,sizeof(mark));
if(fill(i)) if(search(level-)) return true;
memcpy(mark,temp,sizeof(mark));
}
return false;
} int main(){ while(~scanf("%d",&n)){
if(!n) break;
memset(mark,,sizeof(mark));
ans=;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
scanf("%d",&mp[i][j]);
dfs(,,mp[][]);
for(maxd=;!search(maxd);maxd++);
printf("%d\n",maxd);
}
return ;
}

UVa11212 编辑书稿

估价函数比较精妙,每次最多让三个元素的后继正确。

为什么是后继呢?因为这个操作的本质就是改变后继...

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm> using namespace std; const int maxn=; struct Node{
int v[maxn];
}; int n,maxd; inline int get_h(int a[]){
int cnt=;
for(int i=;i<n;i++)
if(a[i+]!=a[i]+) cnt++;
return cnt;
} void move(Node &Start,Node &Next,int I,int J,int K){
for(int i=;i<=K-J-;i++)
Next.v[i+I]=Start.v[J++i];
for(int i=;i<=J-I;i++)
Next.v[K-J+I+i]=Start.v[i+I];
} bool dfs(int level,Node s){
if(get_h(s.v)>*level) return false;
if(get_h(s.v)==) return true; Node next;
for(int i=;i<=n;i++)
for(int j=i;j<=n;j++)
for(int k=j+;k<=n;k++){
memcpy(next.v,s.v,sizeof(s.v));
move(s,next,i,j,k);
if(dfs(level-,next)) return true;
}
return false;
} int main(){
#ifndef ONLINE_JUDGE
freopen("11212.in","r",stdin);
freopen("11212.out","w",stdout);
#endif int kase=;
Node a0; while(~scanf("%d",&n)){
if(!n) break;
for(int i=;i<=n;i++)
scanf("%d",&a0.v[i]);
if(!get_h(a0.v)){
printf("Case %d: 0\n",++kase);
continue;
} for(maxd=;!dfs(maxd,a0);maxd++);
printf("Case %d: %d\n",++kase,maxd);
} return ;
}

迭代启发式搜索 IDA*的更多相关文章

  1. 【2020-8-21】【数字游戏】【启发式搜索IDA*】

    有这么一个游戏: 写出一个1-N的排列a[i],然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少1,直到只剩下一个数字位置.下面是一个例子: ...

  2. 【题解】AcWing 193. 算乘方的牛

    原题链接 题目描述 约翰的奶牛希望能够非常快速地计算一个数字的整数幂P(1 <= P <= 20,000)是多少,这需要你的帮助. 在它们计算得到最终结果的过程中只能保留两个工作变量用于中 ...

  3. 【Uva 12558】 Egyptian Fractions (HARD version) (迭代加深搜,IDA*)

    IDA* 就是iterative deepening(迭代深搜)+A*(启发式搜索) 启发式搜索就是设计估价函数进行的搜索(可以减很多枝哦~) 这题... 理论上可以回溯,但是解答树非常恐怖,深度没有 ...

  4. 小结:A* & IDA* & 迭代深搜

    概要: 在dfs中,如果答案的深度很小但是却很宽,而且bfs还不一定好做的情况下,我们就综合bfs的优点,结合dfs的思想,进行有限制的dfs.在这里A*.IDA*和迭代深搜都是对dfs的优化,因此放 ...

  5. 迭代,IDA*

    1.codevs1288 题意:对于一个分数a/b(a!=1),将它表示为1/x + 1/y + 1/z ……的形式,x,y,z……互不相同 多解取加数少的,加数相同时,取最小的分数最大的. 思路:经 ...

  6. 埃及分数 迭代加深搜索 IDA*

    迭代加深搜索 IDA* 首先枚举当前选择的分数个数上限maxd,进行迭代加深 之后进行估价,假设当前分数之和为a,目标分数为b,当前考虑分数为1/c,那么如果1/c×(maxd - d)< a ...

  7. 迭代加深 A* IDA* 初探

    并没有有用的东西, 只是用来水的. 今天看搜索,想起来了A*和IDA* 看A*去了.... 啥玩意啊这是,他们代码为啥这么长??.... 看完了,...代码怎么写啊?? .....算了,直接看题吧 找 ...

  8. UVA 11212 Editing a Book [迭代加深搜索IDA*]

    11212 Editing a Book You have n equal-length paragraphs numbered 1 to n. Now you want to arrange the ...

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

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

随机推荐

  1. [leetcode]_Merge Two Sorted Lists

    题目:合并两个有序单链表 思路:一开始想复杂了,以为必须在原链表上修改(绕来绕去还AC了,但是思路相当绕),其实没有,按照正常地合并两个数组同样的方法也对. 代码: public ListNode m ...

  2. 解决:JS如何取得当前正在执行的function的名字

    代码如下 function getFName(fn){ return (/^[\s\(]*function(?:\s+([\w$_][\w\d$_]*))?\(/).exec(fn.toString( ...

  3. Cassandra 之 入门

    1.到官网下载压缩包. http://cassandra.apache.org/download/ 我下载的是最新的 apache-cassandra-2.1.2-bin.tar.gz 另外:语言支持 ...

  4. linux中文显示乱码的解决办法

    linux中文显示乱码的解决办法 linux中文显示乱码是一件让人很头疼的事情. linux中文显示乱码的解决办法:[root@kk]#vi /etc/sysconfig/i18n将文件中的内容修改为 ...

  5. 搭通自己的电脑与GitHub的传输通道

    一.远程仓库怎么玩 1. 自己搭建一个运行Git的服务器 Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上,但肯定有一台机器有着最原始的版本库,然后别的机器来克隆这个原始版本库,这 ...

  6. 第十五章 调试及安全性(In .net4.5) 之 管理程序集

    1. 概述 本章将介绍 什么是程序集.如何强命名程序集.如何把程序集放入GAC.程序集版本 以及 WinMD程序集. 2. 主要内容 2.1 什么是程序集 程序集(Assembly)概念的出现,是为了 ...

  7. 北京汽车官网经销商信息抓取(解析html标签)

    1.网站地址http://www.baicmotor.com/dealer.php 2.使用firefox查看后发现,此网站的信息未使用json数据,而是简单那的html页面而已 3.使用pyquer ...

  8. android 中单选和复选框监听操作

    单选按钮RadioGroup.复选框CheckBox都有OnCheckedChangeListener事件,我们一起了解一下. package com.genwoxue.oncheckedchange ...

  9. HTML5 API 之 history

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  10. C# Sql 触发器

    触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程.触发器主要是通过事件进行触发被自动调用执行的.而存储过程可以通过存储过程的名称被调用. Ø 什么是触发器 触发器对表进行插入.更新.删 ...