IDA*学习笔记(uva10384和codevs2495)
来源:互联网 发布:金牛软件官网 编辑:程序博客网 时间:2024/05/29 15:42
迭代加深和A*都是常用的搜索方法,当它们融汇贯通的时候,会发生很奇妙的事情……
题意
有些格子上有墙,可以推墙到相邻格子上(前提是相邻格子的位置上没有墙),求走出迷宫的一条可行道路。
分析
由于要不断地推墙,所以可以走重复格子,这样就会无休止地走下去,所以我们只能用迭代加深,限定每次深搜走几步了。
然后是寻路的话自然可以用A*搞一搞,每次判断当前格子到最近出口的直线距离,如果当前步数+预计最短距离>限定步数的话,可以剪个枝。
最后随便搞一搞就AC了。
代码
#include<iostream>#include<cstdio>#include<cstring>#include<climits>#include<iomanip>#include<algorithm>#include<queue>using namespace std;int read(){ int q=0;char ch=' '; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9')q=q*10+ch-'0',ch=getchar(); return q;}int sx,sy,d,tot;//W:1,N:2,E:4,S:8int ma[5][7];int mvx[5]={0,0,0,1,-1},mvy[5]={0,1,-1,0,0},wal[5]={0,4,1,8,2};int op[5]={0,1,4,2,8};char s[5]={' ','E','W','S','N'};char ans[1005];int h(int x,int y){ int i,re=INT_MAX; for(i=1;i<=4;i++){ if(!(ma[i][1]&wal[2]))re=min(re,abs(x-i)+abs(y-1)); if(!(ma[i][6]&wal[1]))re=min(re,abs(x-i)+abs(y-6)); } for(i=1;i<=6;i++){ if(!(ma[1][i]&wal[4]))re=min(re,abs(x-1)+abs(y-i)); if(!(ma[4][i]&wal[3]))re=min(re,abs(x-4)+abs(y-i)); } return re;}bool dfs(int x,int y,int dep){ if(h(x,y)+dep>d)return 0; if(dep==d){ if((x==1||x==4||y==1||y==6)&&!h(x,y)){ if(x==1&&!(ma[x][y]&wal[4]))ans[++tot]=s[4]; else if(x==4&&!(ma[x][y]&wal[3]))ans[++tot]=s[3]; else if(y==1&&!(ma[x][y]&wal[2]))ans[++tot]=s[2]; else ans[++tot]=s[1]; return 1; } return 0; } for(int i=1;i<=4;i++){ int tx=x+mvx[i],ty=y+mvy[i]; if(tx<1||ty<1||tx>4||ty>6)continue; if(!(ma[x][y]&wal[i]))//没墙 {if(dfs(tx,ty,dep+1)){ans[++tot]=s[i];return 1;}} else {//推墙 int ttx=tx+mvx[i],tty=ty+mvy[i]; if(ma[tx][ty]&wal[i])continue; ma[x][y]-=wal[i];ma[tx][ty]+=wal[i];ma[tx][ty]-=op[i]; if(ttx>=1&&ttx<=4&&tty>=1&&tty<=6)ma[ttx][tty]+=op[i]; if(dfs(tx,ty,dep+1)){ans[++tot]=s[i];return 1;} ma[x][y]+=wal[i];ma[tx][ty]-=wal[i];ma[tx][ty]+=op[i]; if(ttx>=1&&ttx<=4&&tty>=1&&tty<=6)ma[ttx][tty]-=op[i]; } } return 0;}int main(){ int i,j; while(1){ sy=read();sx=read(); if(!sx&&!sy)break; for(i=1;i<=4;i++) for(j=1;j<=6;j++)ma[i][j]=read(); for(d=0;;d++){tot=0;if(dfs(sx,sy,0))break;}//从0开始 for(i=tot;i>=1;i--)printf("%c",ans[i]); printf("\n"); } return 0;}
拓展练习题
codevs2495水叮当的舞步。
中文题就不题意了…..
广搜没办法判重,肯定会爆空间。深搜又难剪枝,绝对会爆时间,这道题我用广搜做了两个多小时,只拿了10分,血的教训啊……
这种时候就要考虑迭代加深和A*的优化了,迭代加深可以缓解广搜空间的问题,而A*则可以成为深搜的极好优化手段。我们先想想迭代加深,那么可以规定最多跳多少步。而在当前状态下最优解是剩余颜色的数量,所以我们考虑用剩余颜色作为A*的估价函数。
还有一个优化图,就是将左上角联通色块变成“1”,它旁边的都变成“2”,剩下的变成“0”,这样方便我们写估价函数和寻找可以扩展的色块。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<climits>#include<cstdlib>#include<iomanip>#include<algorithm>using namespace std;//颜色是0到5int mvx[5]={0,1,-1,0,0},mvy[5]={0,0,0,1,-1};int ma[9][9],ok[9][9];//ma是毯子,ok是一个优化图int dlx[65],dly[65];bool v[6];int m,n,ans;int gj(int color){//估价函数,处理剩余颜色数量 memset(v,0,sizeof(v)); int i,j,sum=0; for(i=1;i<=n;i++) for(j=1;j<=n;j++){ if(ok[i][j]!=1&&v[ma[i][j]]==0){ v[ma[i][j]]=1;sum++; } } return sum;}void bfs(int sx,int sy,int color){//采用广搜寻找扩展的状态 int i,j,k,tx,ty; int head=1,tail=1; dlx[1]=sx;dly[1]=sy;ok[sx][sy]=1; while(head<=tail){ for(i=1;i<=4;i++){ tx=mvx[i]+dlx[head]; ty=mvy[i]+dly[head]; if(tx>=1&&tx<=n&&ty>=1&&ty<=n&&ok[tx][ty]==0){ if(ma[tx][ty]==color){ ok[tx][ty]=1; tail++;dlx[tail]=tx;dly[tail]=ty; } else {ok[tx][ty]=2;}//在联通块旁边 } } head++; }}bool dfs(int d,int f,int now,int color){ int i,j,k; int bj=0; if(now+f>d){return 0;}//如果当前解+剩余最优解>规定层数,剪枝 if(f==0){return 1;}//如果没有其它色块了,就找到了解。 int bf[9][9];//注意,由于搜到下层会改变bf的值,所以bf要在函数里定义 for(i=0;i<=5;i++){ bj=0; if(i==color)continue;//如果i=color相当于不染色 for(j=1;j<=n;j++) for(k=1;k<=n;k++)bf[j][k]=ok[j][k];//bf数组备份一个ok for(j=1;j<=n;j++) for(k=1;k<=n;k++){ if(ok[j][k]==2&&ma[j][k]==i){ bj=1;bfs(j,k,i); } } if(bj==1){ if(dfs(d,gj(i),now+1,i)==1){return 1;} for(j=1;j<=n;j++) for(k=1;k<=n;k++)ok[j][k]=bf[j][k]; } } for(j=1;j<=n;j++)//将ok变回来 for(k=1;k<=n;k++)ok[j][k]=bf[j][k]; return 0;}int main(){ int i,j,k; while(1){ scanf("%d",&n); memset(ok,0,sizeof(ok)); if(n==0)break; for(i=1;i<=n;i++) for(j=1;j<=n;j++){ scanf("%d",&ma[i][j]); } bfs(1,1,ma[1][1]);//确认左上角联通块 for(ans=0;ans<=n*n;ans++){//一定要从0开始,不然一开始就是所有色块一样的毯子没有答案 if(dfs(ans,gj(ma[1][1]),0,ma[1][1])==1){ printf("%d\n",ans); break; } } } return 0;}
0 0
- IDA*学习笔记(uva10384和codevs2495)
- IDA学习笔记
- IDA 学习笔记
- IDA学习笔记
- IDA学习笔记
- IDA学习笔记之寻找OnInitDialog
- IDA学习笔记--VS2008按钮事件捕捉
- 【启发式搜索】A*与IDA*学习笔记
- IDA笔记
- IDA学习
- 使用IDA远程调试APK中的so,学习笔记
- Ida windbg笔记
- IDA个人使用笔记
- ida动态调试笔记
- 初用 IDA 笔记
- IDA 使用笔记
- IDA脚本笔记(一)
- IDA Pro 基础学习
- 面试题四:替换空格
- Caffe CNN特征可视化
- navicat for mysql 破解方法
- c++基本知识
- HDU 2570 迷障
- IDA*学习笔记(uva10384和codevs2495)
- hibernate更新或保存语句不执行
- 目标跟踪:KCF运行流程图(matlab版本)
- 指针和变量
- 网站高并发高负载系统架构
- 新建maven项目pom报错的问题
- android 连接商米POSV1内置打印机
- 使用visual studio code进行go语言环境搭建
- POJ 1072 Puzzle Out 笔记