hdu-4127 Flood-it!(IDA*算法)
来源:互联网 发布:好玩的java web项目 编辑:程序博客网 时间:2024/05/17 17:14
今天做的福州赛区区域赛的题目重现,一整场都在抠这道题仍然无法AC,时间卡的很紧,不过其实也是自己的搜索学的实在太差,紫书上刷的最少的就是第七章的题 。
我一开始就看出了这道题需要IDA*算法,但是昨天才看的还没能深入理解,通过赛后补这道题,感觉整体思路有了一个新的突破 。
IDA*算法就是迭代加深搜索和A*算法的结合,迭代加深搜索非常简单,就是从小到大枚举深度上限,适合求解深度未知的或者像该题一样需要求最小迭代次数的题目 。
A*算法的精髓是写一个估价函数, 如何写呢? 其实就是一个剪枝,通过计算预估一个比较松的下界,也就是预估从当前到达目标至少还要递归多少层,如果它加上当前深度d大于最大深度maxd,应当剪枝 。 事实上,IDA*算法的剪枝函数一般格式也都是这样的 : d + h() > maxd 时剪枝 。有时候也不必严格的在代码里写出h()函数,只是要想清楚在什么情况下不可能在当前深度限制下出解即可 。
另一个非常重要的问题是如何对递归程序进行优化 。其实在场上我已经写出了估价函数,但是仍然超时 ,其原因就是我递归的太多了 。大家都知道如果扩展一颗完整的解答树,那么时间复杂度将极其可怕 ,而我写的暴力程序如果去掉估价函数,就是一颗完整的解答树 。
事实上我做了很多无用的递归 , 大家可以想象一棵树,如果在第一开始就递归一个无用的分支,那么将会对造成极大的浪费 。
我是在每一层枚举6种颜色,都染上看看结果,其实答案只可能是染和当前连通块相邻的颜色(当前连通块就是和左上角元素相连的相同颜色的块)。 所以我们不妨在每一层里加个循环来找与之相邻的颜色,只递归他们 。 看似我们在每一层多加了个循环,浪费了时间,可是和次方级的解答树相比可以忽略不计了~因为我们剪掉了很多树枝 。
这给了我们大家一个启示: 宁可在每一层递归中多跑两个循环,也要想办法减少无用的递归 !
大家可以刷刷紫书上的埃及分数和编辑书稿 ,都很经典 。当然,我的第七章是刷的最少的,也是时候该补补了~
细节见代码:
#include<bits/stdc++.h>using namespace std;const int maxn = 15;int n,maxd,a[maxn][maxn];int vis[maxn][maxn];int dx[] = { 0,1,0,-1,1,-1,-1,1 };int dy[] = { 1,0,-1,0,1,-1,1,-1 };void dfs2(int r,int c,int col) { //更新vis[i][j]数组,给vis[i][j] == 2的变成1,与之相邻的变成2 vis[r][c] = 1; for(int i=0;i<4;++i) { int x = r+dx[i]; int y = c+dy[i]; if(x < 0 || x >=n || y < 0 || y >= n ) continue; if(vis[x][y] == 1 ) continue; vis[x][y] = 2; if(a[x][y] == col) dfs2(x,y,col); }}int H() { int maze[8],cnt = 0; memset(maze,0,sizeof(maze)); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(vis[i][j]==1) continue; if(!maze[a[i][j]]) { maze[a[i][j]]++; cnt++; } } } return cnt;}int filled(int col) { int cnt = 0; for(int i=0;i<n;i++) for(int j=0;j<n;j++){ if(a[i][j] != col) continue; if(vis[i][j] == 2) { //只有当vis[i][j] == 2且与col同色的才染色 cnt++; dfs2(i,j,col); } } return cnt;//返回染色的个数}bool dfs(int d) { if(d == maxd) return H()==0; if( ( H() + d ) > maxd ) return false; int vi[maxn][maxn]; memcpy(vi,vis,sizeof(vi)); for(int i=0;i<6;i++) { if(filled(i) == 0) continue; //没有符合要求的i颜色的块与之相邻 if(dfs(d+1)) return true; memcpy(vis,vi,sizeof(vis)); } return false;}int main() { while(~scanf("%d",&n)&&n) { for(int i=0;i<n;++i) for(int j=0;j<n;++j) scanf("%d",&a[i][j]); memset(vis,0,sizeof(vis)); dfs2(0,0,a[0][0]); for(maxd = 0; ; ++maxd) if(dfs(0)) break; printf("%d\n",maxd); } return 0;}
- hdu-4127 Flood-it!(IDA*算法)
- hdu Flood-it!(IDA*算法)
- HDU 4127 Flood-it!(IDA*)
- HDU 4127 Flood-it!(IDA*搜索)
- hdu 4127 Flood-it! (IDA+bfs)
- HDU 4127 Flood-it! (IDA*+BFS)
- HDU-2871 Flood-it!(IDA*)
- HDU 4127 Flood-it!(11年福州 IDA*搜索)
- HDU 4127Flood-it!
- HDU 4127 Flood-it!
- hdu4127 Flood-it! (IDA*)
- hdu 4127 Flood-it! 搜索
- IDA* UVA 1505 - Flood-it!
- poj 4007 \ hdu 4127 Flood-it!
- ID(dfs+bfs)-hdu-4127-Flood-it!
- HDU 4127 Flood-it! (迭代加深搜索)
- hdu 1813(IDA*算法+dfs)
- hdu 2234 IDA*算法
- struct的初始化及其构造函数
- iOS-为视图添加阴影
- JAVA在ACM中的几点应用
- 数论 - 线性筛法与积性函数
- JAVA接口的用法
- hdu-4127 Flood-it!(IDA*算法)
- 黑马程序员--- objective-c 封装 set与get
- 字符串处理
- STL几个(set map vector string)用法
- Java学习第十七天
- HADOOP 集群安装配置
- Java Annotation详解+自定义java注解(一)
- 每天学点java—文档注释
- 日期分类