题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5335
题面:
2 2 2 11 11 3 3 001 111 101
111 101
//如果之前的搜索最远的1用的是深搜,那么需扩栈,如果是广搜就不必了 #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstdio> #include <string> #include <algorithm> #include <cstring> #include <vector> #include <queue> using namespace std; //map存原图 char map[1005][1005]; //vis访问标记,able标识该点是否可以从0可达 bool vis[1005][1005],able[1005][1005]; //path记录路径,cnt为路径的下标 int t,n,m,xx,yy,path[2010],cnt=0; //dir为四个方向 int dir[4][2]={-1,0,0,1,1,0,0,-1}; //每个节点,即位置 struct node { int x,y; node (int xx,int yy) { x=xx; y=yy; } }; //判断是否越界 bool Inside(int x,int y) { if(x>=0&&x<n&&y>=0&&y<m) return true; return false; } queue <node> q; //搜索能够通过0达到的位置 void bfss() { int tx,ty; q.push(node(0,0)); node tmp(0,0); while(!q.empty()) { tmp=q.front(); q.pop(); //4个方向扩展 for(int i=0;i<4;i++) { tx=tmp.x+dir[i][0]; ty=tmp.y+dir[i][1]; if(Inside(tx,ty)&&!vis[tx][ty]) { vis[tx][ty]=1; if(map[tx][ty]=='0') { //able代表该点可达 able[tx][ty]=1; q.push(node(tx,ty)); } } } } } //qe存过程中的点,v0存0的位置,v1存1的位置 queue <node> qe; vector <node> v0; vector <node> v1; bool rea[1005][1005]; //搜索最短,且字典序最小的路径 void bfs() { while(!qe.empty()) qe.pop(); int tx,ty,sz; bool sign=false; //rea访问标记 memset(rea,0,sizeof(rea)); node tmp(0,0); while(1) { //如果之前出现了可达的0 if(v0.size()) { //那么当前路径位置就取0 path[cnt++]=0; sz=v0.size(); for(int i=0;i<sz;i++) qe.push(v0[i]); } //如果没有出现过0,都是1 else { //那么当前路径位置就取1 path[cnt++]=1; sz=v1.size(); for(int i=0;i<sz;i++) qe.push(v1[i]); } //清空 v0.clear(); v1.clear(); //将qe中的点的下一步位置存到v0,v1中 while(!qe.empty()) { tmp=qe.front(); qe.pop(); //向下 tx=tmp.x+1; ty=tmp.y; //因为rea数组,每个点最多进入队列一次 if(Inside(tx,ty)&&(!rea[tx][ty])) { rea[tx][ty]=1; if(map[tx][ty]=='0') v0.push_back(node(tx,ty)); else v1.push_back(node(tx,ty)); } //向右 tx=tmp.x; ty=tmp.y+1; if(Inside(tx,ty)&&(!rea[tx][ty])) { rea[tx][ty]=1; if(map[tx][ty]=='0') v0.push_back(node(tx,ty)); else v1.push_back(node(tx,ty)); } } //没有点了,说明已到达终点 if((v0.size()==0)&&(v1.size()==0)) break; } } int main() { int minn=0,x,y,z=1; bool flag; scanf("%d",&t); while(t--) { //读入 cnt=0; scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%s",map[i]); } //起点为1,从起点开始寻路 if(map[0][0]=='1') { v1.push_back(node(0,0)); } //起点为0,先找到最远的点们,然后开始寻路 else { memset(vis,0,sizeof(vis)); memset(able,0,sizeof(able)); bfss(); vis[0][0]=able[0][0]=1; minn=0; flag=false; //从离终点最近的斜线开始扫 for(int i=1;i<=m;i++) { for(int j=1;j<=i;j++) { x=n-j; y=m-(i+1-j); //只有x+y最大的且合法的点,才会被加入队列(此处为向量) if(x+y>=minn) { //该点左边或者上边是可达的 if((Inside(x-1,y)&&able[x-1][y])||(Inside(x,y-1)&&able[x][y-1])) { minn=x+y; if(map[x][y]=='1') v1.push_back(node(x,y)); } } else { flag=true; break; } } if(flag)break; } } // if(!flag) { //扫第一条边那的斜线 for(int i=n-1;i>=1;i--) { for(int j=1;j<=i;j++) { if(x+y>=minn) { x=i-j; y=j-1; if((Inside(x-1,y)&&able[x-1][y])||(Inside(x,y-1)&&able[x][y-1])) { minn=x+y; if(map[x][y]=='1') v1.push_back(node(x,y)); } } else { flag=true; break; } } } } //如果有全都为0的路径,直接输出0 if(v1.size()==0) { printf("0\n"); continue; } //寻路 bfs(); //输出 for(int i=0;i<cnt;i++) printf("%d",path[i]); printf("\n"); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5335 Walk Out (搜索+贪心,超详解)经典
原文地址:http://blog.csdn.net/david_jett/article/details/47185303