您的位置:首页 > 其它

迭代加深搜索:POJ3921

2012-10-13 16:42 155 查看
自认为简单的搜索还是可以的,但是经过了这道题过后,我彻底否定自己了!这道题让我看到了搜索的境界:DFS(迭代)+BFS。

以前我一直以为图论的题只能用图论的算法来做,而我做不出来,肯定是图论的有些算法没学习好!这道题让我看到了:图论算法的本质是搜索。以前似乎在哪里听到这样的说法,但是没注意,就算注意到了也没有领悟到!回头再写迷宫的时候,发现其实迷宫其实也可以转化成图来进行搜索。

这道题的思路是这样的:先用bfs找到一条最短路,然后枚举删除每个点。删除点的时候,可以用迭代加深。先枚举所有删除K个点的情况,如果无解,则枚举删除K+1个点的情况!

#include<stdio.h>
#include<string.h>
#define MM 4010
#define MN 100
struct aaa{
int s,f,next;
};
aaa edge[MM];
int head[MN],now;

int n,m,k;

bool rem[MN];//false表示该点没删除,true表示该删除了
int path[MN];
int cpath[MN][MN];
int que[MN];

int ite;//表示迭代次数
int finds;//表示是否找到解
void init(){
memset(head,0,sizeof(head));
now=0;
}

void addEdge(int s,int f){
now++;edge[now].s=s;edge[now].f=f;edge[now].next=head[s];head[s]=now;
}
//在有向图中利用广度优先搜索找路
void bfs(){
int lp,rp;
memset(path,0,sizeof(path));
lp=rp=0;
que[rp++]=1;
//找与1相连的点
while(lp<rp){//队列不为空
int v=que[lp++];
for(int idx=head[v];idx;idx=edge[idx].next){
if(!rem[edge[idx].f]&&path[edge[idx].f]==0){//确实,这个挺巧妙的 能过滤一些边,还能避免环的出现
que[rp++]=edge[idx].f;
path[edge[idx].f]=edge[idx].s;
if(edge[idx].f==n)break;
}
}
if(path
)break;
}
}
void dfs(int deep){
if(finds)return;//如果已经找到就不用再找了
bfs();//找一条路
if(path
==0){//如果不可到达,则不用找了
finds=true;
return;
}
int lpos=-1;
int v=n;
while(v){
cpath[deep][++lpos]=v;
v=path[v];
}
if(lpos>k){//找到的最短路大小 k,找到了,不用找了
finds=true;
return;
}
if(deep>ite)return;//如果深度到了,也不用找了
for(int i=1;i<lpos;i++){
rem[cpath[deep][i]]=true;
dfs(deep+1);
rem[cpath[deep][i]]=false;
}

}
int make(){
finds=false;
for(int i=0;i<=n;i++){
ite=i;
memset(rem,0,sizeof(rem));
dfs(1);
if(finds)return i;
}
return n;
}
int main(){
while(1){
scanf("%d %d %d",&n,&m,&k);
if(n==0&&m==0&&k==0)break;
int s,f;
init();
for(int i=0;i<m;i++){
scanf("%d %d",&s,&f);
addEdge(s,f);
}
printf("%d\n",make());
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  搜索 POJ3921